OSDN Git Service

dwarf2: Move CFI output routines to dwarf2cfi.c.
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index a95ed7a..6469506 100644 (file)
@@ -122,17 +122,6 @@ int vms_file_stats_name (const char *, long long *, long *, char *, int *);
  #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)
@@ -168,38 +157,9 @@ static GTY(()) section *debug_str_section;
 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
@@ -216,15 +176,6 @@ static GTY(()) section *debug_frame_section;
 #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 \
@@ -233,33 +184,12 @@ static GTY(()) section *debug_frame_section;
 #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;
@@ -286,23 +216,13 @@ static GTY(()) section *cold_text_section;
 /* 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)
@@ -340,23 +260,6 @@ static GTY(()) rtx current_unit_personality;
 #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. */
 
@@ -459,98 +362,6 @@ stripattributes (const char *s)
   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.  */
@@ -700,432 +511,6 @@ dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi)
     }
 }
 
-/* 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
@@ -1313,7 +698,7 @@ output_call_frame_info (int for_eh)
   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.  */
@@ -1330,14 +715,15 @@ output_call_frame_info (int for_eh)
     {
       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;
@@ -1490,10 +876,9 @@ output_call_frame_info (int for_eh)
   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))
@@ -1564,6 +949,31 @@ dwarf2out_do_cfi_startproc (bool second)
     }
 }
 
+/* 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.  */
 
@@ -1601,41 +1011,19 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
   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.  */
@@ -1669,7 +1057,6 @@ void
 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
@@ -1678,8 +1065,7 @@ dwarf2out_vms_end_prologue (unsigned int line ATTRIBUTE_UNUSED,
                               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
@@ -1690,10 +1076,9 @@ void
 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;
 
@@ -1727,24 +1112,13 @@ dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
   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.  */
@@ -1776,7 +1150,7 @@ void
 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);
 
@@ -1809,14 +1183,17 @@ dwarf2out_switch_text_section (void)
     = (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);
@@ -2315,7 +1692,6 @@ loc_list_plus_const (dw_loc_list_ref list_head, HOST_WIDE_INT offset)
 #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.  */
@@ -2499,7 +1875,7 @@ size_of_loc_descr (dw_loc_descr_ref loc)
 
 /* 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;
@@ -2528,7 +1904,6 @@ size_of_locs (dw_loc_descr_ref loc)
 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
@@ -2898,7 +2273,7 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
    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)
@@ -3077,7 +2452,7 @@ output_loc_operands_raw (dw_loc_descr_ref loc)
     }
 }
 
-static void
+void
 output_loc_sequence_raw (dw_loc_descr_ref loc)
 {
   while (1)
@@ -3110,60 +2485,6 @@ output_loc_sequence_raw (dw_loc_descr_ref loc)
     }
 }
 
-/* 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.  */
@@ -3489,11 +2810,6 @@ typedef struct skeleton_chain_struct
 }
 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.
 
@@ -8460,12 +7776,11 @@ size_of_aranges (void)
     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)
@@ -9353,12 +8668,11 @@ output_aranges (unsigned long aranges_length)
 
   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,
@@ -10860,44 +10174,53 @@ int_loc_descriptor (HOST_WIDE_INT i)
   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)
@@ -10926,7 +10249,7 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset,
 {
   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
@@ -11296,6 +10619,28 @@ scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
                  && (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));
@@ -13491,7 +12836,7 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
                && (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
@@ -13534,9 +12879,9 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
                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;
              }
@@ -15642,7 +14987,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
   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);
@@ -17666,7 +17011,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 
       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.  */
@@ -17712,9 +17057,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
          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)
            {
@@ -17795,7 +17140,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 
 #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);
@@ -22452,7 +21797,8 @@ dwarf2out_finish (const char *filename)
     }
   else
     {
-      unsigned fde_idx = 0;
+      unsigned fde_idx;
+      dw_fde_ref fde;
       bool range_list_added = false;
 
       if (text_section_used)
@@ -22462,10 +21808,8 @@ dwarf2out_finish (const char *filename)
        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);