OSDN Git Service

gcc/ChangeLog:
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 614871e..669948b 100644 (file)
@@ -110,6 +110,9 @@ static void dwarf2out_source_line (unsigned int, const char *);
 #define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO)
 #endif
 
+/* Save the result of dwarf2out_do_frame across PCH.  */
+static GTY(()) bool saved_do_cfi_asm = 0;
+
 /* Decide whether we want to emit frame unwind information for the current
    translation unit.  */
 
@@ -121,7 +124,7 @@ dwarf2out_do_frame (void)
      we're not going to output frame or unwind info.  */
   return (write_symbols == DWARF2_DEBUG
          || write_symbols == VMS_AND_DWARF2_DEBUG
-         || DWARF2_FRAME_INFO
+         || DWARF2_FRAME_INFO || saved_do_cfi_asm
 #ifdef DWARF2_UNWIND_INFO
          || (DWARF2_UNWIND_INFO
              && (flag_unwind_tables
@@ -142,7 +145,7 @@ dwarf2out_do_cfi_asm (void)
 #endif
   if (!flag_dwarf2_cfi_asm || !dwarf2out_do_frame ())
     return false;
-  if (!eh_personality_libfunc)
+  if (saved_do_cfi_asm || !eh_personality_libfunc)
     return true;
   if (!HAVE_GAS_CFI_PERSONALITY_DIRECTIVE)
     return false;
@@ -156,6 +159,7 @@ dwarf2out_do_cfi_asm (void)
   if ((enc & 0x70) != 0 && (enc & 0x70) != DW_EH_PE_pcrel)
     return false;
 
+  saved_do_cfi_asm = true;
   return true;
 }
 
@@ -411,7 +415,8 @@ static void reg_save (const char *, unsigned, unsigned, HOST_WIDE_INT);
 #ifdef DWARF2_UNWIND_INFO
 static void initial_return_save (rtx);
 #endif
-static HOST_WIDE_INT stack_adjust_offset (const_rtx);
+static HOST_WIDE_INT stack_adjust_offset (const_rtx, HOST_WIDE_INT,
+                                         HOST_WIDE_INT);
 static void output_cfi (dw_cfi_ref, dw_fde_ref, int);
 static void output_cfi_directive (dw_cfi_ref);
 static void output_call_frame_info (int);
@@ -1110,7 +1115,8 @@ initial_return_save (rtx rtl)
    contains.  */
 
 static HOST_WIDE_INT
-stack_adjust_offset (const_rtx pattern)
+stack_adjust_offset (const_rtx pattern, HOST_WIDE_INT cur_args_size,
+                    HOST_WIDE_INT cur_offset)
 {
   const_rtx src = SET_SRC (pattern);
   const_rtx dest = SET_DEST (pattern);
@@ -1119,18 +1125,34 @@ stack_adjust_offset (const_rtx pattern)
 
   if (dest == stack_pointer_rtx)
     {
-      /* (set (reg sp) (plus (reg sp) (const_int))) */
       code = GET_CODE (src);
+
+      /* Assume (set (reg sp) (reg whatever)) sets args_size
+        level to 0.  */
+      if (code == REG && src != stack_pointer_rtx)
+       {
+         offset = -cur_args_size;
+#ifndef STACK_GROWS_DOWNWARD
+         offset = -offset;
+#endif
+         return offset - cur_offset;
+       }
+
       if (! (code == PLUS || code == MINUS)
          || XEXP (src, 0) != stack_pointer_rtx
          || GET_CODE (XEXP (src, 1)) != CONST_INT)
        return 0;
 
+      /* (set (reg sp) (plus (reg sp) (const_int))) */
       offset = INTVAL (XEXP (src, 1));
       if (code == PLUS)
        offset = -offset;
+      return offset;
     }
-  else if (MEM_P (dest))
+
+  if (MEM_P (src) && !MEM_P (dest))
+    dest = src;
+  if (MEM_P (dest))
     {
       /* (set (mem (pre_dec (reg sp))) (foo)) */
       src = XEXP (dest, 0);
@@ -1199,7 +1221,7 @@ compute_barrier_args_size_1 (rtx insn, HOST_WIDE_INT cur_args_size,
          || sibcall_epilogue_contains (insn))
        /* Nothing */;
       else if (GET_CODE (PATTERN (insn)) == SET)
-       offset = stack_adjust_offset (PATTERN (insn));
+       offset = stack_adjust_offset (PATTERN (insn), cur_args_size, 0);
       else if (GET_CODE (PATTERN (insn)) == PARALLEL
               || GET_CODE (PATTERN (insn)) == SEQUENCE)
        {
@@ -1207,7 +1229,8 @@ compute_barrier_args_size_1 (rtx insn, HOST_WIDE_INT cur_args_size,
             for them.  */
          for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
            if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
-             offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i));
+             offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i),
+                                            cur_args_size, offset);
        }
     }
   else
@@ -1224,7 +1247,7 @@ compute_barrier_args_size_1 (rtx insn, HOST_WIDE_INT cur_args_size,
                rtx elem = XVECEXP (expr, 0, i);
 
                if (GET_CODE (elem) == SET && !RTX_FRAME_RELATED_P (elem))
-                 offset += stack_adjust_offset (elem);
+                 offset += stack_adjust_offset (elem, cur_args_size, offset);
              }
        }
     }
@@ -1312,13 +1335,25 @@ compute_barrier_args_size (void)
              body = PATTERN (insn);
              if (GET_CODE (body) == SEQUENCE)
                {
+                 HOST_WIDE_INT dest_args_size = cur_args_size;
                  for (i = 1; i < XVECLEN (body, 0); i++)
+                   if (INSN_ANNULLED_BRANCH_P (XVECEXP (body, 0, 0))
+                       && INSN_FROM_TARGET_P (XVECEXP (body, 0, i)))
+                     dest_args_size
+                       = compute_barrier_args_size_1 (XVECEXP (body, 0, i),
+                                                      dest_args_size, &next);
+                   else
+                     cur_args_size
+                       = compute_barrier_args_size_1 (XVECEXP (body, 0, i),
+                                                      cur_args_size, &next);
+
+                 if (INSN_ANNULLED_BRANCH_P (XVECEXP (body, 0, 0)))
+                   compute_barrier_args_size_1 (XVECEXP (body, 0, 0),
+                                                dest_args_size, &next);
+                 else
                    cur_args_size
-                     = compute_barrier_args_size_1 (XVECEXP (body, 0, i),
+                     = compute_barrier_args_size_1 (XVECEXP (body, 0, 0),
                                                     cur_args_size, &next);
-                 cur_args_size
-                   = compute_barrier_args_size_1 (XVECEXP (body, 0, 0),
-                                                  cur_args_size, &next);
                }
              else
                cur_args_size
@@ -1359,6 +1394,14 @@ dwarf2out_stack_adjust (rtx insn, bool after_p)
   if (prologue_epilogue_contains (insn) || sibcall_epilogue_contains (insn))
     return;
 
+  /* If INSN is an instruction from target of an annulled branch, the
+     effects are for the target only and so current argument size
+     shouldn't change at all.  */
+  if (final_sequence
+      && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))
+      && INSN_FROM_TARGET_P (insn))
+    return;
+
   /* If only calls can throw, and we have a frame pointer,
      save up adjustments until we see the CALL_INSN.  */
   if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM)
@@ -1404,7 +1447,7 @@ dwarf2out_stack_adjust (rtx insn, bool after_p)
 #endif
     }
   else if (GET_CODE (PATTERN (insn)) == SET)
-    offset = stack_adjust_offset (PATTERN (insn));
+    offset = stack_adjust_offset (PATTERN (insn), args_size, 0);
   else if (GET_CODE (PATTERN (insn)) == PARALLEL
           || GET_CODE (PATTERN (insn)) == SEQUENCE)
     {
@@ -1412,7 +1455,8 @@ dwarf2out_stack_adjust (rtx insn, bool after_p)
         for them.  */
       for (offset = 0, i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
        if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
-         offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i));
+         offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i),
+                                        args_size, offset);
     }
   else
     return;
@@ -1871,7 +1915,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
            {
              /* Stack adjustment combining might combine some post-prologue
                 stack adjustment into a prologue stack adjustment.  */
-             HOST_WIDE_INT offset = stack_adjust_offset (elem);
+             HOST_WIDE_INT offset = stack_adjust_offset (elem, args_size, 0);
 
              if (offset != 0)
                dwarf2out_args_size_adjust (offset, label);
@@ -16248,6 +16292,37 @@ prune_unused_types_mark (dw_die_ref die, int dokids)
     }
 }
 
+/* For local classes, look if any static member functions were emitted
+   and if so, mark them.  */
+
+static void
+prune_unused_types_walk_local_classes (dw_die_ref die)
+{
+  dw_die_ref c;
+
+  if (die->die_mark == 2)
+    return;
+
+  switch (die->die_tag)
+    {
+    case DW_TAG_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_class_type:
+      break;
+
+    case DW_TAG_subprogram:
+      if (!get_AT_flag (die, DW_AT_declaration)
+         || die->die_definition != NULL)
+       prune_unused_types_mark (die, 1);
+      return;
+
+    default:
+      return;
+    }
+
+  /* Mark children.  */
+  FOR_EACH_CHILD (die, c, prune_unused_types_walk_local_classes (c));
+}
 
 /* Walk the tree DIE and mark types that we actually use.  */
 
@@ -16256,12 +16331,34 @@ prune_unused_types_walk (dw_die_ref die)
 {
   dw_die_ref c;
 
-  /* Don't do anything if this node is already marked.  */
-  if (die->die_mark)
+  /* Don't do anything if this node is already marked and
+     children have been marked as well.  */
+  if (die->die_mark == 2)
     return;
 
   switch (die->die_tag)
     {
+    case DW_TAG_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_class_type:
+      if (die->die_perennial_p)
+       break;
+
+      for (c = die->die_parent; c; c = c->die_parent)
+       if (c->die_tag == DW_TAG_subprogram)
+         break;
+
+      /* Finding used static member functions inside of classes
+        is needed just for local classes, because for other classes
+        static member function DIEs with DW_AT_specification
+        are emitted outside of the DW_TAG_*_type.  If we ever change
+        it, we'd need to call this even for non-local classes.  */
+      if (c)
+       prune_unused_types_walk_local_classes (die);
+
+      /* It's a type node --- don't mark it.  */
+      return;
+
     case DW_TAG_const_type:
     case DW_TAG_packed_type:
     case DW_TAG_pointer_type:
@@ -16269,9 +16366,6 @@ prune_unused_types_walk (dw_die_ref die)
     case DW_TAG_volatile_type:
     case DW_TAG_typedef:
     case DW_TAG_array_type:
-    case DW_TAG_structure_type:
-    case DW_TAG_union_type:
-    case DW_TAG_class_type:
     case DW_TAG_interface_type:
     case DW_TAG_friend:
     case DW_TAG_variant_part:
@@ -16293,10 +16387,15 @@ prune_unused_types_walk (dw_die_ref die)
       break;
   }
 
-  die->die_mark = 1;
+  if (die->die_mark == 0)
+    {
+      die->die_mark = 1;
+
+      /* Now, mark any dies referenced from here.  */
+      prune_unused_types_walk_attribs (die);
+    }
 
-  /* Now, mark any dies referenced from here.  */
-  prune_unused_types_walk_attribs (die);
+  die->die_mark = 2;
 
   /* Mark children.  */
   FOR_EACH_CHILD (die, c, prune_unused_types_walk (c));