OSDN Git Service

* g++.dg/rtti/tinfo1.C: Remove xfails.
[pf3gnuchains/gcc-fork.git] / gcc / function.c
index 452de0c..82776e7 100644 (file)
@@ -287,8 +287,6 @@ pop_function_context_from (tree context ATTRIBUTE_UNUSED)
   current_function_decl = p->decl;
   reg_renumber = 0;
 
-  restore_emit_status (p);
-
   lang_hooks.function.leave_nested (p);
 
   /* Reset variables that have known state during rtx generation.  */
@@ -535,7 +533,6 @@ insert_slot_to_list (struct temp_slot *temp, struct temp_slot **list)
 static struct temp_slot **
 temp_slots_at_level (int level)
 {
-  level++;
 
   if (!used_temp_slots)
     VARRAY_GENERIC_PTR_INIT (used_temp_slots, 3, "used_temp_slots");
@@ -831,7 +828,7 @@ assign_temp (tree type_or_decl, int keep, int memory_required,
       if (decl && size == -1
          && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST)
        {
-         error ("%Jsize of variable '%D' is too large", decl, decl);
+         error ("%Jsize of variable %qD is too large", decl, decl);
          size = 1;
        }
 
@@ -1346,10 +1343,20 @@ instantiate_decl (rtx x, HOST_WIDE_INT size, int valid_only)
   enum machine_mode mode;
   rtx addr;
 
+  if (x == 0)
+    return;
+
+  /* If this is a CONCAT, recurse for the pieces.  */
+  if (GET_CODE (x) == CONCAT)
+    {
+      instantiate_decl (XEXP (x, 0), size / 2, valid_only);
+      instantiate_decl (XEXP (x, 1), size / 2, valid_only);
+      return;
+    }
+
   /* If this is not a MEM, no need to do anything.  Similarly if the
      address is a constant or a register that is not a virtual register.  */
-
-  if (x == 0 || !MEM_P (x))
+  if (!MEM_P (x))
     return;
 
   addr = XEXP (x, 0);
@@ -1432,7 +1439,7 @@ static void
 instantiate_virtual_regs_lossage (rtx insn)
 {
   gcc_assert (asm_noperands (PATTERN (insn)) >= 0);
-  error_for_asm (insn, "impossible constraint in `asm'");
+  error_for_asm (insn, "impossible constraint in %<asm%>");
   delete_insn (insn);
 }
 /* Given a pointer to a piece of rtx and an optional pointer to the
@@ -2513,8 +2520,12 @@ assign_parm_setup_block_p (struct assign_parm_data_one *data)
     return true;
 
 #ifdef BLOCK_REG_PADDING
-  if (data->locate.where_pad == (BYTES_BIG_ENDIAN ? upward : downward)
-      && GET_MODE_SIZE (data->promoted_mode) < UNITS_PER_WORD)
+  /* Only assign_parm_setup_block knows how to deal with register arguments
+     that are padded at the least significant end.  */
+  if (REG_P (data->entry_parm)
+      && GET_MODE_SIZE (data->promoted_mode) < UNITS_PER_WORD
+      && (BLOCK_REG_PADDING (data->passed_mode, data->passed_type, 1)
+         == (BYTES_BIG_ENDIAN ? upward : downward)))
     return true;
 #endif
 
@@ -2535,12 +2546,32 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
   if (GET_CODE (entry_parm) == PARALLEL
       && data->nominal_mode != BLKmode
       && XVECLEN (entry_parm, 0) > 1
-      && optimize)
+      && use_register_for_decl (parm))
     {
       rtx parmreg = gen_reg_rtx (data->nominal_mode);
 
-      emit_group_store (parmreg, entry_parm, data->nominal_type,
-                       int_size_in_bytes (data->nominal_type));
+      /* For values returned in multiple registers, handle possible
+        incompatible calls to emit_group_store.
+
+        For example, the following would be invalid, and would have to
+        be fixed by the conditional below:
+
+          emit_group_store ((reg:SF), (parallel:DF))
+          emit_group_store ((reg:SI), (parallel:DI))
+
+        An example of this are doubles in e500 v2:
+          (parallel:DF (expr_list (reg:SI) (const_int 0))
+                       (expr_list (reg:SI) (const_int 4))).  */
+      if (data->nominal_mode != data->passed_mode)
+       {
+         rtx t = gen_reg_rtx (GET_MODE (entry_parm));
+         emit_group_store (t, entry_parm, NULL_TREE,
+                           GET_MODE_SIZE (GET_MODE (entry_parm)));
+         convert_move (parmreg, t, 0);
+       }
+      else
+       emit_group_store (parmreg, entry_parm, data->nominal_type,
+                         int_size_in_bytes (data->nominal_type));
       SET_DECL_RTL (parm, parmreg);
       return;
     }
@@ -2719,7 +2750,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
 
       /* TREE_USED gets set erroneously during expand_assignment.  */
       save_tree_used = TREE_USED (parm);
-      expand_assignment (parm, make_tree (data->nominal_type, tempreg), 0);
+      expand_assignment (parm, make_tree (data->nominal_type, tempreg));
       TREE_USED (parm) = save_tree_used;
       all->conversion_insns = get_insns ();
       end_sequence ();
@@ -3454,7 +3485,8 @@ setjmp_vars_warning (tree block)
          && DECL_RTL_SET_P (decl)
          && REG_P (DECL_RTL (decl))
          && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
-       warning ("%Jvariable '%D' might be clobbered by `longjmp' or `vfork'",
+       warning ("%Jvariable %qD might be clobbered by %<longjmp%>"
+                " or %<vfork%>",
                 decl, decl);
     }
 
@@ -3474,7 +3506,7 @@ setjmp_args_warning (void)
     if (DECL_RTL (decl) != 0
        && REG_P (DECL_RTL (decl))
        && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
-      warning ("%Jargument '%D' might be clobbered by `longjmp' or `vfork'",
+      warning ("%Jargument %qD might be clobbered by %<longjmp%> or %<vfork%>",
               decl, decl);
 }
 
@@ -4198,7 +4230,7 @@ do_warn_unused_parameter (tree fn)
        decl; decl = TREE_CHAIN (decl))
     if (!TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
        && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl))
-      warning ("%Junused parameter '%D'", decl, decl);
+      warning ("%Junused parameter %qD", decl, decl);
 }
 
 static GTY(()) rtx initial_trampoline;
@@ -4955,6 +4987,7 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
 #if defined (HAVE_epilogue) || defined(HAVE_return)
   rtx epilogue_end = NULL_RTX;
 #endif
+  edge_iterator ei;
 
 #ifdef HAVE_prologue
   if (HAVE_prologue)
@@ -4974,16 +5007,16 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
       /* Can't deal with multiple successors of the entry block
          at the moment.  Function should always have at least one
          entry point.  */
-      gcc_assert (ENTRY_BLOCK_PTR->succ && !ENTRY_BLOCK_PTR->succ->succ_next);
+      gcc_assert (EDGE_COUNT (ENTRY_BLOCK_PTR->succs) == 1);
 
-      insert_insn_on_edge (seq, ENTRY_BLOCK_PTR->succ);
+      insert_insn_on_edge (seq, EDGE_SUCC (ENTRY_BLOCK_PTR, 0));
       inserted = 1;
     }
 #endif
 
   /* If the exit block has no non-fake predecessors, we don't need
      an epilogue.  */
-  for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
+  FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
     if ((e->flags & EDGE_FAKE) == 0)
       break;
   if (e == NULL)
@@ -4999,10 +5032,9 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
         emit (conditional) return instructions.  */
 
       basic_block last;
-      edge e_next;
       rtx label;
 
-      for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
+      FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
        if (e->flags & EDGE_FALLTHRU)
          break;
       if (e == NULL)
@@ -5020,6 +5052,7 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
 
       if (BB_HEAD (last) == label && LABEL_P (label))
        {
+         edge_iterator ei2;
          rtx epilogue_line_note = NULL_RTX;
 
          /* Locate the line number associated with the closing brace,
@@ -5033,18 +5066,23 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
                break;
              }
 
-         for (e = last->pred; e; e = e_next)
+         for (ei2 = ei_start (last->preds); (e = ei_safe_edge (ei2)); )
            {
              basic_block bb = e->src;
              rtx jump;
 
-             e_next = e->pred_next;
              if (bb == ENTRY_BLOCK_PTR)
-               continue;
+               {
+                 ei_next (&ei2);
+                 continue;
+               }
 
              jump = BB_END (bb);
              if (!JUMP_P (jump) || JUMP_LABEL (jump) != label)
-               continue;
+               {
+                 ei_next (&ei2);
+                 continue;
+               }
 
              /* If we have an unconditional jump, we can replace that
                 with a simple return instruction.  */
@@ -5059,16 +5097,25 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
              else if (condjump_p (jump))
                {
                  if (! redirect_jump (jump, 0, 0))
-                   continue;
+                   {
+                     ei_next (&ei2);
+                     continue;
+                   }
 
                  /* If this block has only one successor, it both jumps
                     and falls through to the fallthru block, so we can't
                     delete the edge.  */
-                 if (bb->succ->succ_next == NULL)
-                   continue;
+                 if (EDGE_COUNT (bb->succs) == 1)
+                   {
+                     ei_next (&ei2);
+                     continue;
+                   }
                }
              else
-               continue;
+               {
+                 ei_next (&ei2);
+                 continue;
+               }
 
              /* Fix up the CFG for the successful change we just made.  */
              redirect_edge_succ (e, EXIT_BLOCK_PTR);
@@ -5080,7 +5127,7 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
          emit_barrier_after (BB_END (last));
          emit_return_into_block (last, epilogue_line_note);
          epilogue_end = BB_END (last);
-         last->succ->flags &= ~EDGE_FALLTHRU;
+         EDGE_SUCC (last, 0)->flags &= ~EDGE_FALLTHRU;
          goto epilogue_done;
        }
     }
@@ -5090,7 +5137,7 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
      There really shouldn't be a mixture -- either all should have
      been converted or none, however...  */
 
-  for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
+  FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
     if (e->flags & EDGE_FALLTHRU)
       break;
   if (e == NULL)
@@ -5151,7 +5198,7 @@ epilogue_done:
 
 #ifdef HAVE_sibcall_epilogue
   /* Emit sibling epilogues before any sibling call sites.  */
-  for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
+  for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
     {
       basic_block bb = e->src;
       rtx insn = BB_END (bb);
@@ -5160,7 +5207,10 @@ epilogue_done:
 
       if (!CALL_P (insn)
          || ! SIBLING_CALL_P (insn))
-       continue;
+       {
+         ei_next (&ei);
+         continue;
+       }
 
       start_sequence ();
       emit_insn (gen_sibcall_epilogue ());
@@ -5175,6 +5225,7 @@ epilogue_done:
 
       i = PREV_INSN (insn);
       newinsn = emit_insn_before (seq, insn);
+      ei_next (&ei);
     }
 #endif