#pragma GCC poison DWARF2_UNWIND_INFO DWARF2_FRAME_INFO
#endif
-#ifndef INCOMING_RETURN_ADDR_RTX
-#define INCOMING_RETURN_ADDR_RTX (gcc_unreachable (), NULL_RTX)
-#endif
-
-/* 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
-
/* The size of the target's pointer type. */
#ifndef PTR_SIZE
#define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
static GTY(()) section *debug_ranges_section;
static GTY(()) section *debug_frame_section;
-/* How to start an assembler comment. */
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START ";#"
-#endif
-
/* Maximum size (in bytes) of an artificially generated label. */
#define MAX_ARTIFICIAL_LABEL_BYTES 30
-/* The size of addresses as they appear in the Dwarf 2 data.
- Some architectures use word addresses to refer to code locations,
- but Dwarf 2 info always uses byte addresses. On such machines,
- Dwarf 2 addresses need to be larger than the architecture's
- pointers. */
-#ifndef DWARF2_ADDR_SIZE
-#define DWARF2_ADDR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
-#endif
-
-/* The size in bytes of a DWARF field indicating an offset or length
- relative to a debug info section, specified to be 4 bytes in the
- DWARF-2 specification. The SGI/MIPS ABI defines it to be the same
- as PTR_SIZE. */
-
-#ifndef DWARF_OFFSET_SIZE
-#define DWARF_OFFSET_SIZE 4
-#endif
-
-/* The size in bytes of a DWARF 4 type signature. */
-
-#ifndef DWARF_TYPE_SIGNATURE_SIZE
-#define DWARF_TYPE_SIGNATURE_SIZE 8
-#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
#define DWARF_ROUND(SIZE,BOUNDARY) \
((((SIZE) + (BOUNDARY) - 1) / (BOUNDARY)) * (BOUNDARY))
-/* Offsets recorded in opcodes are a multiple of this alignment factor. */
-#ifndef DWARF_CIE_DATA_ALIGNMENT
-#ifdef STACK_GROWS_DOWNWARD
-#define DWARF_CIE_DATA_ALIGNMENT (-((int) UNITS_PER_WORD))
-#else
-#define DWARF_CIE_DATA_ALIGNMENT ((int) UNITS_PER_WORD)
-#endif
-#endif
-
/* CIE identifier. */
#if HOST_BITS_PER_WIDE_INT >= 64
#define DWARF_CIE_ID \
#define DWARF_CIE_ID DW_CIE_ID
#endif
-/* A pointer to the base of a table that contains frame description
- information for each routine. */
-static GTY((length ("fde_table_allocated"))) dw_fde_ref fde_table;
-
-/* Number of elements currently allocated for fde_table. */
-static GTY(()) unsigned fde_table_allocated;
-
-/* Number of elements in fde_table currently 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
-
-/* Get the current fde_table entry we should use. */
+DEF_VEC_P (dw_fde_ref);
+DEF_VEC_ALLOC_P (dw_fde_ref, gc);
-dw_fde_ref
-current_fde (void)
-{
- return fde_table_in_use ? &fde_table[fde_table_in_use - 1] : NULL;
-}
-
-/* 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;
+/* A vector for a table that contains frame description
+ information for each routine. */
+static GTY(()) VEC(dw_fde_ref, gc) *fde_vec;
struct GTY(()) indirect_string_node {
const char *str;
/* Forward declarations for functions defined in this file. */
static char *stripattributes (const char *);
-static void output_cfi (dw_cfi_ref, dw_fde_ref, int);
static void output_call_frame_info (int);
static void dwarf2out_note_section_used (void);
-/* Support for complex CFA locations. */
-static void output_cfa_loc (dw_cfi_ref, int);
-static void output_cfa_loc_raw (dw_cfi_ref);
-
/* Personality decl of current unit. Used only when assembler does not support
personality CFI. */
static GTY(()) rtx current_unit_personality;
-/* How to start an assembler comment. */
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START ";#"
-#endif
-
/* Data and reference forms for relocatable data. */
#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)
#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
#define LN_PROLOG_AS_LABEL "LASLTP"
#define LN_PROLOG_END_LABEL "LELTP"
#define DIE_LABEL_PREFIX "DW"
-
-/* The DWARF 2 CFA column which tracks the return address. Normally this
- is the column for PC, or the first column after all of the hard
- registers. */
-#ifndef DWARF_FRAME_RETURN_COLUMN
-#ifdef PC_REGNUM
-#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (PC_REGNUM)
-#else
-#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGISTERS
-#endif
-#endif
-
-/* The mapping from gcc register number to DWARF 2 CFA column number. By
- default, we just provide columns for all registers. */
-#ifndef DWARF_FRAME_REGNUM
-#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
-#endif
\f
/* Match the base name of a file to the base name of a compilation unit. */
return stripped;
}
-/* Divide OFF by DWARF_CIE_DATA_ALIGNMENT, asserting no remainder. */
-
-static inline HOST_WIDE_INT
-div_data_align (HOST_WIDE_INT off)
-{
- HOST_WIDE_INT r = off / DWARF_CIE_DATA_ALIGNMENT;
- gcc_assert (r * DWARF_CIE_DATA_ALIGNMENT == off);
- return r;
-}
-
-/* Return true if we need a signed version of a given opcode
- (e.g. DW_CFA_offset_extended_sf vs DW_CFA_offset_extended). */
-
-static inline bool
-need_data_align_sf_opcode (HOST_WIDE_INT off)
-{
- return DWARF_CIE_DATA_ALIGNMENT < 0 ? off > 0 : off < 0;
-}
-
-/* Convert a DWARF call frame info. operation to its string name */
-
-static const char *
-dwarf_cfi_name (unsigned int cfi_opc)
-{
- switch (cfi_opc)
- {
- case DW_CFA_advance_loc:
- return "DW_CFA_advance_loc";
- case DW_CFA_offset:
- return "DW_CFA_offset";
- case DW_CFA_restore:
- return "DW_CFA_restore";
- case DW_CFA_nop:
- return "DW_CFA_nop";
- case DW_CFA_set_loc:
- return "DW_CFA_set_loc";
- case DW_CFA_advance_loc1:
- return "DW_CFA_advance_loc1";
- case DW_CFA_advance_loc2:
- return "DW_CFA_advance_loc2";
- case DW_CFA_advance_loc4:
- return "DW_CFA_advance_loc4";
- case DW_CFA_offset_extended:
- return "DW_CFA_offset_extended";
- case DW_CFA_restore_extended:
- return "DW_CFA_restore_extended";
- case DW_CFA_undefined:
- return "DW_CFA_undefined";
- case DW_CFA_same_value:
- return "DW_CFA_same_value";
- case DW_CFA_register:
- return "DW_CFA_register";
- case DW_CFA_remember_state:
- return "DW_CFA_remember_state";
- case DW_CFA_restore_state:
- return "DW_CFA_restore_state";
- case DW_CFA_def_cfa:
- return "DW_CFA_def_cfa";
- case DW_CFA_def_cfa_register:
- return "DW_CFA_def_cfa_register";
- case DW_CFA_def_cfa_offset:
- return "DW_CFA_def_cfa_offset";
-
- /* DWARF 3 */
- case DW_CFA_def_cfa_expression:
- return "DW_CFA_def_cfa_expression";
- case DW_CFA_expression:
- return "DW_CFA_expression";
- case DW_CFA_offset_extended_sf:
- return "DW_CFA_offset_extended_sf";
- case DW_CFA_def_cfa_sf:
- return "DW_CFA_def_cfa_sf";
- case DW_CFA_def_cfa_offset_sf:
- return "DW_CFA_def_cfa_offset_sf";
-
- /* SGI/MIPS specific */
- case DW_CFA_MIPS_advance_loc8:
- return "DW_CFA_MIPS_advance_loc8";
-
- /* GNU extensions */
- case DW_CFA_GNU_window_save:
- return "DW_CFA_GNU_window_save";
- case DW_CFA_GNU_args_size:
- return "DW_CFA_GNU_args_size";
- case DW_CFA_GNU_negative_offset_extended:
- return "DW_CFA_GNU_negative_offset_extended";
-
- default:
- return "DW_CFA_<unknown>";
- }
-}
-
/* Switch [BACK] to eh_frame_section. If we don't have an eh_frame_section,
switch to the data section instead, and write out a synthetic start label
for collect2 the first time around. */
}
}
-/* Output a Call Frame Information opcode and its operand(s). */
-
-static void
-output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
-{
- unsigned long r;
- HOST_WIDE_INT off;
-
- 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 " HOST_WIDE_INT_PRINT_HEX,
- ((unsigned HOST_WIDE_INT)
- cfi->dw_cfi_oprnd1.dw_cfi_offset));
- else if (cfi->dw_cfi_opc == DW_CFA_offset)
- {
- 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 %#lx", r);
- off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
- dw2_asm_output_data_uleb128 (off, NULL);
- }
- else if (cfi->dw_cfi_opc == DW_CFA_restore)
- {
- 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 %#lx", r);
- }
- else
- {
- dw2_asm_output_data (1, cfi->dw_cfi_opc,
- "%s", dwarf_cfi_name (cfi->dw_cfi_opc));
-
- switch (cfi->dw_cfi_opc)
- {
- case DW_CFA_set_loc:
- 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),
- false, NULL);
- else
- dw2_asm_output_addr (DWARF2_ADDR_SIZE,
- cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL);
- fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
- break;
-
- case DW_CFA_advance_loc1:
- dw2_asm_output_delta (1, cfi->dw_cfi_oprnd1.dw_cfi_addr,
- fde->dw_fde_current_label, NULL);
- fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
- break;
-
- case DW_CFA_advance_loc2:
- dw2_asm_output_delta (2, cfi->dw_cfi_oprnd1.dw_cfi_addr,
- fde->dw_fde_current_label, NULL);
- fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
- break;
-
- case DW_CFA_advance_loc4:
- dw2_asm_output_delta (4, cfi->dw_cfi_oprnd1.dw_cfi_addr,
- fde->dw_fde_current_label, NULL);
- fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
- break;
-
- case DW_CFA_MIPS_advance_loc8:
- dw2_asm_output_delta (8, cfi->dw_cfi_oprnd1.dw_cfi_addr,
- fde->dw_fde_current_label, NULL);
- fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
- break;
-
- case DW_CFA_offset_extended:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
- dw2_asm_output_data_uleb128 (r, NULL);
- off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
- dw2_asm_output_data_uleb128 (off, NULL);
- break;
-
- case DW_CFA_def_cfa:
- 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:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
- dw2_asm_output_data_uleb128 (r, NULL);
- off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
- dw2_asm_output_data_sleb128 (off, NULL);
- break;
-
- case DW_CFA_def_cfa_sf:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
- dw2_asm_output_data_uleb128 (r, NULL);
- off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
- dw2_asm_output_data_sleb128 (off, NULL);
- break;
-
- case DW_CFA_restore_extended:
- case DW_CFA_undefined:
- case DW_CFA_same_value:
- case DW_CFA_def_cfa_register:
- 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:
- 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:
- case DW_CFA_GNU_args_size:
- dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
- break;
-
- case DW_CFA_def_cfa_offset_sf:
- off = div_data_align (cfi->dw_cfi_oprnd1.dw_cfi_offset);
- dw2_asm_output_data_sleb128 (off, NULL);
- break;
-
- case DW_CFA_GNU_window_save:
- break;
-
- case DW_CFA_def_cfa_expression:
- case DW_CFA_expression:
- output_cfa_loc (cfi, for_eh);
- break;
-
- case DW_CFA_GNU_negative_offset_extended:
- /* Obsoleted by DW_CFA_offset_extended_sf. */
- gcc_unreachable ();
-
- default:
- break;
- }
- }
-}
-
-/* Similar, but do it via assembler directives instead. */
-
-static void
-output_cfi_directive (dw_cfi_ref cfi)
-{
- unsigned long r, r2;
-
- switch (cfi->dw_cfi_opc)
- {
- case DW_CFA_advance_loc:
- case DW_CFA_advance_loc1:
- case DW_CFA_advance_loc2:
- case DW_CFA_advance_loc4:
- case DW_CFA_MIPS_advance_loc8:
- case DW_CFA_set_loc:
- /* Should only be created by add_fde_cfi in a code path not
- followed when emitting via directives. The assembler is
- going to take care of this for us. */
- gcc_unreachable ();
-
- case DW_CFA_offset:
- case DW_CFA_offset_extended:
- case DW_CFA_offset_extended_sf:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_offset %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
- r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
- break;
-
- case DW_CFA_restore:
- case DW_CFA_restore_extended:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_restore %lu\n", r);
- break;
-
- case DW_CFA_undefined:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_undefined %lu\n", r);
- break;
-
- case DW_CFA_same_value:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_same_value %lu\n", r);
- break;
-
- case DW_CFA_def_cfa:
- case DW_CFA_def_cfa_sf:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_def_cfa %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
- r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
- break;
-
- case DW_CFA_def_cfa_register:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_def_cfa_register %lu\n", r);
- break;
-
- case DW_CFA_register:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- r2 = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "\t.cfi_register %lu, %lu\n", r, r2);
- break;
-
- case DW_CFA_def_cfa_offset:
- case DW_CFA_def_cfa_offset_sf:
- fprintf (asm_out_file, "\t.cfi_def_cfa_offset "
- HOST_WIDE_INT_PRINT_DEC"\n",
- cfi->dw_cfi_oprnd1.dw_cfi_offset);
- break;
-
- case DW_CFA_remember_state:
- fprintf (asm_out_file, "\t.cfi_remember_state\n");
- break;
- case DW_CFA_restore_state:
- fprintf (asm_out_file, "\t.cfi_restore_state\n");
- break;
-
- case DW_CFA_GNU_args_size:
- fprintf (asm_out_file, "\t.cfi_escape %#x,", DW_CFA_GNU_args_size);
- dw2_asm_output_data_uleb128_raw (cfi->dw_cfi_oprnd1.dw_cfi_offset);
- if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s args_size "HOST_WIDE_INT_PRINT_DEC,
- ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
- fputc ('\n', asm_out_file);
- break;
-
- case DW_CFA_GNU_window_save:
- fprintf (asm_out_file, "\t.cfi_window_save\n");
- break;
-
- case DW_CFA_def_cfa_expression:
- case DW_CFA_expression:
- fprintf (asm_out_file, "\t.cfi_escape %#x,", cfi->dw_cfi_opc);
- output_cfa_loc_raw (cfi);
- fputc ('\n', asm_out_file);
- break;
-
- default:
- gcc_unreachable ();
- }
-}
-
-void
-dwarf2out_emit_cfi (dw_cfi_ref cfi)
-{
- if (dwarf2out_do_cfi_asm ())
- output_cfi_directive (cfi);
-}
-
-/* Output CFIs from VEC, up to index UPTO, to bring current FDE to the
- same state as after executing CFIs in CFI chain. DO_CFI_ASM is
- true if .cfi_* directives shall be emitted, false otherwise. If it
- is false, FDE and FOR_EH are the other arguments to pass to
- output_cfi. */
-
-static void
-output_cfis (cfi_vec vec, int upto, bool do_cfi_asm,
- dw_fde_ref fde, bool for_eh)
-{
- int ix;
- struct dw_cfi_struct cfi_buf;
- dw_cfi_ref cfi2;
- dw_cfi_ref cfi_args_size = NULL, cfi_cfa = NULL, cfi_cfa_offset = NULL;
- VEC(dw_cfi_ref, heap) *regs = VEC_alloc (dw_cfi_ref, heap, 32);
- unsigned int len, idx;
-
- for (ix = 0; ix < upto + 1; ix++)
- {
- dw_cfi_ref cfi = ix < upto ? VEC_index (dw_cfi_ref, vec, ix) : NULL;
- switch (cfi ? cfi->dw_cfi_opc : DW_CFA_nop)
- {
- case DW_CFA_advance_loc:
- case DW_CFA_advance_loc1:
- case DW_CFA_advance_loc2:
- case DW_CFA_advance_loc4:
- case DW_CFA_MIPS_advance_loc8:
- case DW_CFA_set_loc:
- /* All advances should be ignored. */
- break;
- case DW_CFA_remember_state:
- {
- dw_cfi_ref args_size = cfi_args_size;
-
- /* Skip everything between .cfi_remember_state and
- .cfi_restore_state. */
- ix++;
- if (ix == upto)
- goto flush_all;
-
- for (; ix < upto; ix++)
- {
- cfi2 = VEC_index (dw_cfi_ref, vec, ix);
- if (cfi2->dw_cfi_opc == DW_CFA_restore_state)
- break;
- else if (cfi2->dw_cfi_opc == DW_CFA_GNU_args_size)
- args_size = cfi2;
- else
- gcc_assert (cfi2->dw_cfi_opc != DW_CFA_remember_state);
- }
-
- cfi_args_size = args_size;
- break;
- }
- case DW_CFA_GNU_args_size:
- cfi_args_size = cfi;
- break;
- case DW_CFA_GNU_window_save:
- goto flush_all;
- case DW_CFA_offset:
- case DW_CFA_offset_extended:
- case DW_CFA_offset_extended_sf:
- case DW_CFA_restore:
- case DW_CFA_restore_extended:
- case DW_CFA_undefined:
- case DW_CFA_same_value:
- case DW_CFA_register:
- case DW_CFA_val_offset:
- case DW_CFA_val_offset_sf:
- case DW_CFA_expression:
- case DW_CFA_val_expression:
- case DW_CFA_GNU_negative_offset_extended:
- if (VEC_length (dw_cfi_ref, regs)
- <= cfi->dw_cfi_oprnd1.dw_cfi_reg_num)
- VEC_safe_grow_cleared (dw_cfi_ref, heap, regs,
- cfi->dw_cfi_oprnd1.dw_cfi_reg_num + 1);
- VEC_replace (dw_cfi_ref, regs, cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
- cfi);
- break;
- case DW_CFA_def_cfa:
- case DW_CFA_def_cfa_sf:
- case DW_CFA_def_cfa_expression:
- cfi_cfa = cfi;
- cfi_cfa_offset = cfi;
- break;
- case DW_CFA_def_cfa_register:
- cfi_cfa = cfi;
- break;
- case DW_CFA_def_cfa_offset:
- case DW_CFA_def_cfa_offset_sf:
- cfi_cfa_offset = cfi;
- break;
- case DW_CFA_nop:
- gcc_assert (cfi == NULL);
- flush_all:
- len = VEC_length (dw_cfi_ref, regs);
- for (idx = 0; idx < len; idx++)
- {
- cfi2 = VEC_replace (dw_cfi_ref, regs, idx, NULL);
- if (cfi2 != NULL
- && cfi2->dw_cfi_opc != DW_CFA_restore
- && cfi2->dw_cfi_opc != DW_CFA_restore_extended)
- {
- if (do_cfi_asm)
- output_cfi_directive (cfi2);
- else
- output_cfi (cfi2, fde, for_eh);
- }
- }
- if (cfi_cfa && cfi_cfa_offset && cfi_cfa_offset != cfi_cfa)
- {
- gcc_assert (cfi_cfa->dw_cfi_opc != DW_CFA_def_cfa_expression);
- cfi_buf = *cfi_cfa;
- switch (cfi_cfa_offset->dw_cfi_opc)
- {
- case DW_CFA_def_cfa_offset:
- cfi_buf.dw_cfi_opc = DW_CFA_def_cfa;
- cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd1;
- break;
- case DW_CFA_def_cfa_offset_sf:
- cfi_buf.dw_cfi_opc = DW_CFA_def_cfa_sf;
- cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd1;
- break;
- case DW_CFA_def_cfa:
- case DW_CFA_def_cfa_sf:
- cfi_buf.dw_cfi_opc = cfi_cfa_offset->dw_cfi_opc;
- cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd2;
- break;
- default:
- gcc_unreachable ();
- }
- cfi_cfa = &cfi_buf;
- }
- else if (cfi_cfa_offset)
- cfi_cfa = cfi_cfa_offset;
- if (cfi_cfa)
- {
- if (do_cfi_asm)
- output_cfi_directive (cfi_cfa);
- else
- output_cfi (cfi_cfa, fde, for_eh);
- }
- cfi_cfa = NULL;
- cfi_cfa_offset = NULL;
- if (cfi_args_size
- && cfi_args_size->dw_cfi_oprnd1.dw_cfi_offset)
- {
- if (do_cfi_asm)
- output_cfi_directive (cfi_args_size);
- else
- output_cfi (cfi_args_size, fde, for_eh);
- }
- cfi_args_size = NULL;
- if (cfi == NULL)
- {
- VEC_free (dw_cfi_ref, heap, regs);
- return;
- }
- else if (do_cfi_asm)
- output_cfi_directive (cfi);
- else
- output_cfi (cfi, fde, for_eh);
- break;
- default:
- gcc_unreachable ();
- }
- }
-}
-
-/* Like output_cfis, but emit all CFIs in the vector. */
-static void
-output_all_cfis (cfi_vec vec, bool do_cfi_asm,
- dw_fde_ref fde, bool for_eh)
-{
- output_cfis (vec, VEC_length (dw_cfi_ref, vec), do_cfi_asm, fde, for_eh);
-}
-
/* Output one FDE. */
static void
int dw_cie_version;
/* Don't emit a CIE if there won't be any FDEs. */
- if (fde_table_in_use == 0)
+ if (fde_vec == NULL)
return;
/* Nothing to do if the assembler's doing it all. */
{
bool any_eh_needed = false;
- 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_needed_for_eh_p (&fde_table[i]))
- any_eh_needed = true;
- else if (TARGET_USES_WEAK_UNWIND_INFO)
- targetm.asm_out.emit_unwind_label (asm_out_file, fde_table[i].decl,
- 1, 1);
+ FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, i, fde)
+ {
+ if (fde->uses_eh_lsda)
+ any_eh_needed = any_lsda_needed = true;
+ else if (fde_needed_for_eh_p (fde))
+ any_eh_needed = true;
+ else if (TARGET_USES_WEAK_UNWIND_INFO)
+ targetm.asm_out.emit_unwind_label (asm_out_file, fde->decl, 1, 1);
+ }
if (!any_eh_needed)
return;
ASM_OUTPUT_LABEL (asm_out_file, l2);
/* Loop through all of the FDE's. */
- for (i = 0; i < fde_table_in_use; i++)
+ FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, i, fde)
{
unsigned int k;
- fde = &fde_table[i];
/* Don't emit EH unwind info for leaf functions that don't need it. */
if (for_eh && !fde_needed_for_eh_p (fde))
}
}
+/* Allocate CURRENT_FDE. Immediately initialize all we can, noting that
+ this allocation may be done before pass_final. */
+
+dw_fde_ref
+dwarf2out_alloc_current_fde (void)
+{
+ dw_fde_ref fde;
+
+ fde = ggc_alloc_cleared_dw_fde_node ();
+ fde->decl = current_function_decl;
+ fde->funcdef_number = current_function_funcdef_no;
+ fde->fde_index = VEC_length (dw_fde_ref, fde_vec);
+ fde->all_throwers_are_sibcalls = crtl->all_throwers_are_sibcalls;
+ fde->uses_eh_lsda = crtl->uses_eh_lsda;
+ fde->nothrow = crtl->nothrow;
+ fde->drap_reg = INVALID_REGNUM;
+ fde->vdrap_reg = INVALID_REGNUM;
+
+ /* Record the FDE associated with this function. */
+ cfun->fde = fde;
+ VEC_safe_push (dw_fde_ref, gc, fde_vec, fde);
+
+ return fde;
+}
+
/* Output a marker (i.e. a label) for the beginning of a function, before
the prologue. */
if (!do_frame)
return;
- /* Expand the fde table if necessary. */
- if (fde_table_in_use == fde_table_allocated)
- {
- fde_table_allocated += FDE_TABLE_INCREMENT;
- fde_table = GGC_RESIZEVEC (dw_fde_node, fde_table, fde_table_allocated);
- memset (fde_table + fde_table_in_use, 0,
- FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
- }
-
- /* Record the FDE associated with this function. */
- current_funcdef_fde = fde_table_in_use;
+ /* Cater to the various TARGET_ASM_OUTPUT_MI_THUNK implementations that
+ emit insns as rtx but bypass the bulk of rest_of_compilation, which
+ would include pass_dwarf2_frame. If we've not created the FDE yet,
+ do so now. */
+ fde = cfun->fde;
+ if (fde == NULL)
+ fde = dwarf2out_alloc_current_fde ();
- /* Add the new FDE at the end of the fde_table. */
- fde = &fde_table[fde_table_in_use++];
- fde->decl = current_function_decl;
+ /* Initialize the bits of CURRENT_FDE that were not available earlier. */
fde->dw_fde_begin = dup_label;
- fde->dw_fde_end = NULL;
fde->dw_fde_current_label = dup_label;
- fde->dw_fde_second_begin = NULL;
- fde->dw_fde_second_end = NULL;
- fde->dw_fde_vms_end_prologue = NULL;
- fde->dw_fde_vms_begin_epilogue = NULL;
- fde->dw_fde_cfi = VEC_alloc (dw_cfi_ref, gc, 20);
- fde->dw_fde_switch_cfi_index = 0;
- fde->funcdef_number = current_function_funcdef_no;
- fde->all_throwers_are_sibcalls = crtl->all_throwers_are_sibcalls;
- fde->uses_eh_lsda = crtl->uses_eh_lsda;
- fde->nothrow = crtl->nothrow;
- fde->drap_reg = INVALID_REGNUM;
- fde->vdrap_reg = INVALID_REGNUM;
fde->in_std_section = (fnsec == text_section
|| (cold_text_section && fnsec == cold_text_section));
- fde->second_in_std_section = 0;
-
- dwarf2cfi_function_init ();
/* We only want to output line number information for the genuine dwarf2
prologue case, not the eh frame case. */
dwarf2out_vms_end_prologue (unsigned int line ATTRIBUTE_UNUSED,
const char *file ATTRIBUTE_UNUSED)
{
- dw_fde_ref fde;
char label[MAX_ARTIFICIAL_LABEL_BYTES];
/* Output a label to mark the endpoint of the code generated for this
current_function_funcdef_no);
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, PROLOGUE_END_LABEL,
current_function_funcdef_no);
- fde = &fde_table[fde_table_in_use - 1];
- fde->dw_fde_vms_end_prologue = xstrdup (label);
+ cfun->fde->dw_fde_vms_end_prologue = xstrdup (label);
}
/* Output a marker (i.e. a label) for the beginning of the generated code
dwarf2out_vms_begin_epilogue (unsigned int line ATTRIBUTE_UNUSED,
const char *file ATTRIBUTE_UNUSED)
{
- dw_fde_ref fde;
+ dw_fde_ref fde = cfun->fde;
char label[MAX_ARTIFICIAL_LABEL_BYTES];
- fde = &fde_table[fde_table_in_use - 1];
if (fde->dw_fde_vms_begin_epilogue)
return;
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
current_function_funcdef_no);
ASM_OUTPUT_LABEL (asm_out_file, label);
- fde = current_fde ();
+ fde = cfun->fde;
gcc_assert (fde != NULL);
if (fde->dw_fde_second_begin == NULL)
fde->dw_fde_end = xstrdup (label);
}
void
-dwarf2out_frame_init (void)
-{
- /* Allocate the initial hunk of the fde_table. */
- fde_table = ggc_alloc_cleared_vec_dw_fde_node (FDE_TABLE_INCREMENT);
- fde_table_allocated = FDE_TABLE_INCREMENT;
- fde_table_in_use = 0;
-
- dwarf2cfi_frame_init ();
-}
-
-void
dwarf2out_frame_finish (void)
{
/* Output call frame information. */
dwarf2out_switch_text_section (void)
{
section *sect;
- dw_fde_ref fde = current_fde ();
+ dw_fde_ref fde = cfun->fde;
gcc_assert (cfun && fde && fde->dw_fde_second_begin == NULL);
= (sect == text_section
|| (cold_text_section && sect == cold_text_section));
+ fde->dw_fde_switch_cfi_index = VEC_length (dw_cfi_ref, fde->dw_fde_cfi);
+
if (dwarf2out_do_cfi_asm ())
{
dwarf2out_do_cfi_startproc (true);
/* As this is a different FDE, insert all current CFI instructions
again. */
- output_all_cfis (fde->dw_fde_cfi, true, fde, true);
+ output_cfis (fde->dw_fde_cfi, fde->dw_fde_switch_cfi_index,
+ true, fde, true);
}
- fde->dw_fde_switch_cfi_index = VEC_length (dw_cfi_ref, fde->dw_fde_cfi);
+
var_location_switch_text_section ();
set_cur_line_info_table (sect);
#define DWARF_REF_SIZE \
(dwarf_version == 2 ? DWARF2_ADDR_SIZE : DWARF_OFFSET_SIZE)
-static unsigned long size_of_locs (dw_loc_descr_ref);
static unsigned long int get_base_type_offset (dw_die_ref);
/* Return the size of a location descriptor. */
/* Return the size of a series of location descriptors. */
-static unsigned long
+unsigned long
size_of_locs (dw_loc_descr_ref loc)
{
dw_loc_descr_ref l;
static HOST_WIDE_INT extract_int (const unsigned char *, unsigned);
static void get_ref_die_offset_label (char *, dw_die_ref);
static unsigned long int get_ref_die_offset (dw_die_ref);
-static void output_loc_sequence (dw_loc_descr_ref, int);
/* Output location description stack opcode's operands (if any).
The for_eh_or_skip parameter controls whether register numbers are
info). This should be suppressed for the cases that have not been converted
(i.e. symbolic debug info), by setting the parameter < 0. See PR47324. */
-static void
+void
output_loc_sequence (dw_loc_descr_ref loc, int for_eh_or_skip)
{
for (; loc != NULL; loc = loc->dw_loc_next)
}
}
-static void
+void
output_loc_sequence_raw (dw_loc_descr_ref loc)
{
while (1)
}
}
-/* This routine will generate the correct assembly data for a location
- description based on a cfi entry with a complex address. */
-
-static void
-output_cfa_loc (dw_cfi_ref cfi, int for_eh)
-{
- dw_loc_descr_ref loc;
- unsigned long size;
-
- if (cfi->dw_cfi_opc == DW_CFA_expression)
- {
- unsigned r =
- DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
- dw2_asm_output_data (1, r, NULL);
- loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
- }
- else
- loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
-
- /* Output the size of the block. */
- size = size_of_locs (loc);
- dw2_asm_output_data_uleb128 (size, NULL);
-
- /* Now output the operations themselves. */
- output_loc_sequence (loc, for_eh);
-}
-
-/* Similar, but used for .cfi_escape. */
-
-static void
-output_cfa_loc_raw (dw_cfi_ref cfi)
-{
- dw_loc_descr_ref loc;
- unsigned long size;
-
- if (cfi->dw_cfi_opc == DW_CFA_expression)
- {
- unsigned r =
- DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
- fprintf (asm_out_file, "%#x,", r);
- loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
- }
- else
- loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
-
- /* Output the size of the block. */
- size = size_of_locs (loc);
- dw2_asm_output_data_uleb128_raw (size);
- fputc (',', asm_out_file);
-
- /* Now output the operations themselves. */
- output_loc_sequence_raw (loc);
-}
-
/* This function builds a dwarf location descriptor sequence from a
dw_cfa_location, adding the given OFFSET to the result of the
expression. */
}
skeleton_chain_node;
-/* How to start an assembler comment. */
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START ";#"
-#endif
-
/* Define a macro which returns nonzero for a TYPE_DECL which was
implicitly generated for a type.
size += 2 * DWARF2_ADDR_SIZE;
if (have_multiple_function_sections)
{
- unsigned fde_idx = 0;
+ unsigned fde_idx;
+ dw_fde_ref fde;
- for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++)
+ FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, fde_idx, fde)
{
- dw_fde_ref fde = &fde_table[fde_idx];
-
if (!fde->in_std_section)
size += 2 * DWARF2_ADDR_SIZE;
if (fde->dw_fde_second_begin && !fde->second_in_std_section)
if (have_multiple_function_sections)
{
- unsigned fde_idx = 0;
+ unsigned fde_idx;
+ dw_fde_ref fde;
- for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++)
+ FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, fde_idx, fde)
{
- dw_fde_ref fde = &fde_table[fde_idx];
-
if (!fde->in_std_section)
{
dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
return new_loc_descr (op, i, 0);
}
-/* Return loc description representing "address" of integer value.
- This can appear only as toplevel expression. */
+/* Return size_of_locs (int_loc_descriptor (i)) without
+ actually allocating it. */
-static dw_loc_descr_ref
-address_of_int_loc_descriptor (int size, HOST_WIDE_INT i)
+static unsigned long
+size_of_int_loc_descriptor (HOST_WIDE_INT i)
{
- int litsize;
- dw_loc_descr_ref loc_result = NULL;
-
- if (!(dwarf_version >= 4 || !dwarf_strict))
- return NULL;
-
if (i >= 0)
{
if (i <= 31)
- litsize = 1;
+ return 1;
else if (i <= 0xff)
- litsize = 2;
+ return 2;
else if (i <= 0xffff)
- litsize = 3;
+ return 3;
else if (HOST_BITS_PER_WIDE_INT == 32
|| i <= 0xffffffff)
- litsize = 5;
+ return 5;
else
- litsize = 1 + size_of_uleb128 ((unsigned HOST_WIDE_INT) i);
+ return 1 + size_of_uleb128 ((unsigned HOST_WIDE_INT) i);
}
else
{
if (i >= -0x80)
- litsize = 2;
+ return 2;
else if (i >= -0x8000)
- litsize = 3;
+ return 3;
else if (HOST_BITS_PER_WIDE_INT == 32
|| i >= -0x80000000)
- litsize = 5;
+ return 5;
else
- litsize = 1 + size_of_sleb128 (i);
+ return 1 + size_of_sleb128 (i);
}
+}
+
+/* Return loc description representing "address" of integer value.
+ This can appear only as toplevel expression. */
+
+static dw_loc_descr_ref
+address_of_int_loc_descriptor (int size, HOST_WIDE_INT i)
+{
+ int litsize;
+ dw_loc_descr_ref loc_result = NULL;
+
+ if (!(dwarf_version >= 4 || !dwarf_strict))
+ return NULL;
+
+ litsize = size_of_int_loc_descriptor (i);
/* Determine if DW_OP_stack_value or DW_OP_implicit_value
is more compact. For DW_OP_stack_value we need:
litsize + 1 (DW_OP_stack_value)
{
unsigned int regno;
dw_loc_descr_ref result;
- dw_fde_ref fde = current_fde ();
+ dw_fde_ref fde = cfun->fde;
/* We only use "frame base" when we're sure we're talking about the
post-prologue local stack frame. We do this by *not* running
&& (unsigned HOST_WIDE_INT) INTVAL (XEXP (rtl, 1))
== (INTVAL (XEXP (rtl, 1)) & GET_MODE_MASK (op_mode)))))
return compare_loc_descriptor (op, op0, op1);
+
+ /* EQ/NE comparison against constant in narrower type than
+ DWARF2_ADDR_SIZE can be performed either as
+ DW_OP_const1u <shift> DW_OP_shl DW_OP_const* <cst << shift>
+ DW_OP_{eq,ne}
+ or
+ DW_OP_const*u <mode_mask> DW_OP_and DW_OP_const* <cst & mode_mask>
+ DW_OP_{eq,ne}. Pick whatever is shorter. */
+ if (CONST_INT_P (XEXP (rtl, 1))
+ && GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT
+ && (size_of_int_loc_descriptor (shift) + 1
+ + size_of_int_loc_descriptor (INTVAL (XEXP (rtl, 1)) << shift)
+ >= size_of_int_loc_descriptor (GET_MODE_MASK (op_mode)) + 1
+ + size_of_int_loc_descriptor (INTVAL (XEXP (rtl, 1))
+ & GET_MODE_MASK (op_mode))))
+ {
+ add_loc_descr (&op0, int_loc_descriptor (GET_MODE_MASK (op_mode)));
+ add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
+ op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1))
+ & GET_MODE_MASK (op_mode));
+ return compare_loc_descriptor (op, op0, op1);
+ }
}
add_loc_descr (&op0, int_loc_descriptor (shift));
add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0));
&& (node != loc_list->first || loc_list->first->next)
&& current_function_decl)
{
- endname = current_fde ()->dw_fde_end;
+ endname = cfun->fde->dw_fde_end;
range_across_switch = true;
}
/* The variable has a location between NODE->LABEL and
if (node->next)
endname = node->next->label;
else
- endname = current_fde ()->dw_fde_second_end;
+ endname = cfun->fde->dw_fde_second_end;
*listp = new_loc_list (descr,
- current_fde ()->dw_fde_second_begin,
+ cfun->fde->dw_fde_second_begin,
endname, secname);
listp = &(*listp)->dw_loc_next;
}
const char *start_label, *last_label, *section;
dw_cfa_location remember;
- fde = current_fde ();
+ fde = cfun->fde;
gcc_assert (fde != NULL);
section = secname_for_decl (current_function_decl);
if (!flag_reorder_blocks_and_partition)
{
- dw_fde_ref fde = &fde_table[current_funcdef_fde];
+ dw_fde_ref fde = cfun->fde;
if (fde->dw_fde_begin)
{
/* We have already generated the labels. */
add_pubname (decl, subr_die);
}
else
- { /* Generate pubnames entries for the split function code
- ranges. */
- dw_fde_ref fde = &fde_table[current_funcdef_fde];
+ {
+ /* Generate pubnames entries for the split function code ranges. */
+ dw_fde_ref fde = cfun->fde;
if (fde->dw_fde_second_begin)
{
#ifdef MIPS_DEBUGGING_INFO
/* Add a reference to the FDE for this routine. */
- add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, current_funcdef_fde);
+ add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, cfun->fde->fde_index);
#endif
cfa_fb_offset = CFA_FRAME_BASE_OFFSET (decl);
}
else
{
- unsigned fde_idx = 0;
+ unsigned fde_idx;
+ dw_fde_ref fde;
bool range_list_added = false;
if (text_section_used)
add_ranges_by_labels (comp_unit_die (), cold_text_section_label,
cold_end_label, &range_list_added);
- for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++)
+ FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, fde_idx, fde)
{
- dw_fde_ref fde = &fde_table[fde_idx];
-
if (!fde->in_std_section)
add_ranges_by_labels (comp_unit_die (), fde->dw_fde_begin,
fde->dw_fde_end, &range_list_added);