OSDN Git Service

2008-12-09 Tobias Grosser <grosser@fim.uni-passau.de>
[pf3gnuchains/gcc-fork.git] / gcc / cfgexpand.c
index c9faa49..6eaec30 100644 (file)
@@ -50,20 +50,20 @@ tree
 gimple_assign_rhs_to_tree (gimple stmt)
 {
   tree t;
-  enum gimple_rhs_class class;
+  enum gimple_rhs_class grhs_class;
     
-  class = get_gimple_rhs_class (gimple_expr_code (stmt));
+  grhs_class = get_gimple_rhs_class (gimple_expr_code (stmt));
 
-  if (class == GIMPLE_BINARY_RHS)
+  if (grhs_class == GIMPLE_BINARY_RHS)
     t = build2 (gimple_assign_rhs_code (stmt),
                TREE_TYPE (gimple_assign_lhs (stmt)),
                gimple_assign_rhs1 (stmt),
                gimple_assign_rhs2 (stmt));
-  else if (class == GIMPLE_UNARY_RHS)
+  else if (grhs_class == GIMPLE_UNARY_RHS)
     t = build1 (gimple_assign_rhs_code (stmt),
                TREE_TYPE (gimple_assign_lhs (stmt)),
                gimple_assign_rhs1 (stmt));
-  else if (class == GIMPLE_SINGLE_RHS)
+  else if (grhs_class == GIMPLE_SINGLE_RHS)
     t = gimple_assign_rhs1 (stmt);
   else
     gcc_unreachable ();
@@ -216,16 +216,8 @@ gimple_to_tree (gimple stmt)
         
        t = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
 
-        fn = gimple_call_fn (stmt);
-        if (TREE_CODE (fn) == FUNCTION_DECL)
-          CALL_EXPR_FN (t) = build1 (ADDR_EXPR,
-                                     build_pointer_type (TREE_TYPE (fn)),
-                                     fn);
-        else
-          CALL_EXPR_FN (t) = fn;
-        
+        CALL_EXPR_FN (t) = gimple_call_fn (stmt);
         TREE_TYPE (t) = gimple_call_return_type (stmt);
-
        CALL_EXPR_STATIC_CHAIN (t) = gimple_call_chain (stmt);
 
        for (i = 0; i < gimple_call_num_args (stmt); i++)
@@ -253,7 +245,9 @@ gimple_to_tree (gimple stmt)
 
         /* Record the original call statement, as it may be used
            to retrieve profile information during expansion.  */
-       if (TREE_CODE (fn) == FUNCTION_DECL && DECL_BUILT_IN (fn))
+
+       if ((fn = gimple_call_fndecl (stmt)) != NULL_TREE
+           && DECL_BUILT_IN (fn))
          {
            ann = get_tree_common_ann (t);
            ann->stmt = stmt;
@@ -368,15 +362,11 @@ release_stmt_tree (gimple stmt, tree stmt_tree)
     case GIMPLE_CALL:
       if (gimple_call_lhs (stmt))
        {
-         if (TREE_CODE (gimple_call_fn (stmt)) == FUNCTION_DECL)
-           ggc_free (CALL_EXPR_FN (TREE_OPERAND (stmt_tree, 1)));
          ann = tree_common_ann (TREE_OPERAND (stmt_tree, 1));
          if (ann)
            ggc_free (ann);
          ggc_free (TREE_OPERAND (stmt_tree, 1));
        }
-      else if (TREE_CODE (gimple_call_fn (stmt)) == FUNCTION_DECL)
-       ggc_free (CALL_EXPR_FN (stmt_tree));
       break;
     default:
       break;
@@ -1450,7 +1440,7 @@ estimated_stack_frame_size (void)
 static void
 expand_used_vars (void)
 {
-  tree t, outer_block = DECL_INITIAL (current_function_decl);
+  tree t, next, outer_block = DECL_INITIAL (current_function_decl);
 
   /* Compute the phase of the stack frame for this function.  */
   {
@@ -1463,11 +1453,15 @@ expand_used_vars (void)
 
   /* At this point all variables on the local_decls with TREE_USED
      set are not associated with any block scope.  Lay them out.  */
-  for (t = cfun->local_decls; t; t = TREE_CHAIN (t))
+  t = cfun->local_decls;
+  cfun->local_decls = NULL_TREE;
+  for (; t; t = next)
     {
       tree var = TREE_VALUE (t);
       bool expand_now = false;
 
+      next = TREE_CHAIN (t);
+
       /* We didn't set a block for static or extern because it's hard
         to tell the difference between a global variable (re)declared
         in a local scope, and one that's really declared there to
@@ -1494,9 +1488,25 @@ expand_used_vars (void)
       TREE_USED (var) = 1;
 
       if (expand_now)
-       expand_one_var (var, true, true);
+       {
+         expand_one_var (var, true, true);
+         if (DECL_ARTIFICIAL (var) && !DECL_IGNORED_P (var))
+           {
+             rtx rtl = DECL_RTL_IF_SET (var);
+
+             /* Keep artificial non-ignored vars in cfun->local_decls
+                chain until instantiate_decls.  */
+             if (rtl && (MEM_P (rtl) || GET_CODE (rtl) == CONCAT))
+               {
+                 TREE_CHAIN (t) = cfun->local_decls;
+                 cfun->local_decls = t;
+                 continue;
+               }
+           }
+       }
+
+      ggc_free (t);
     }
-  cfun->local_decls = NULL_TREE;
 
   /* At this point, all variables within the block tree with TREE_USED
      set are actually used by the optimized function.  Lay them out.  */
@@ -1656,7 +1666,12 @@ expand_gimple_cond (basic_block bb, gimple stmt)
       add_reg_br_prob_note (last, true_edge->probability);
       maybe_dump_rtl_for_gimple_stmt (stmt, last);
       if (true_edge->goto_locus)
-       set_curr_insn_source_location (true_edge->goto_locus);
+       {
+         set_curr_insn_source_location (true_edge->goto_locus);
+         set_curr_insn_block (true_edge->goto_block);
+         true_edge->goto_locus = curr_insn_locator ();
+       }
+      true_edge->goto_block = NULL;
       false_edge->flags |= EDGE_FALLTHRU;
       ggc_free (pred);
       return NULL;
@@ -1667,7 +1682,12 @@ expand_gimple_cond (basic_block bb, gimple stmt)
       add_reg_br_prob_note (last, false_edge->probability);
       maybe_dump_rtl_for_gimple_stmt (stmt, last);
       if (false_edge->goto_locus)
-       set_curr_insn_source_location (false_edge->goto_locus);
+       {
+         set_curr_insn_source_location (false_edge->goto_locus);
+         set_curr_insn_block (false_edge->goto_block);
+         false_edge->goto_locus = curr_insn_locator ();
+       }
+      false_edge->goto_block = NULL;
       true_edge->flags |= EDGE_FALLTHRU;
       ggc_free (pred);
       return NULL;
@@ -1676,6 +1696,13 @@ expand_gimple_cond (basic_block bb, gimple stmt)
   jumpif (pred, label_rtx_for_bb (true_edge->dest));
   add_reg_br_prob_note (last, true_edge->probability);
   last = get_last_insn ();
+  if (false_edge->goto_locus)
+    {
+      set_curr_insn_source_location (false_edge->goto_locus);
+      set_curr_insn_block (false_edge->goto_block);
+      false_edge->goto_locus = curr_insn_locator ();
+    }
+  false_edge->goto_block = NULL;
   emit_jump (label_rtx_for_bb (false_edge->dest));
 
   BB_END (bb) = last;
@@ -1698,8 +1725,13 @@ expand_gimple_cond (basic_block bb, gimple stmt)
 
   maybe_dump_rtl_for_gimple_stmt (stmt, last2);
 
-  if (false_edge->goto_locus)
-    set_curr_insn_source_location (false_edge->goto_locus);
+  if (true_edge->goto_locus)
+    {
+      set_curr_insn_source_location (true_edge->goto_locus);
+      set_curr_insn_block (true_edge->goto_block);
+      true_edge->goto_locus = curr_insn_locator ();
+    }
+  true_edge->goto_block = NULL;
 
   ggc_free (pred);
   return new_bb;
@@ -1952,19 +1984,21 @@ expand_gimple_basic_block (basic_block bb)
        }
     }
 
-  /* Expand implicit goto.  */
+  /* Expand implicit goto and convert goto_locus.  */
   FOR_EACH_EDGE (e, ei, bb->succs)
     {
-      if (e->flags & EDGE_FALLTHRU)
-       break;
-    }
-
-  if (e && e->dest != bb->next_bb)
-    {
-      emit_jump (label_rtx_for_bb (e->dest));
-      if (e->goto_locus)
-        set_curr_insn_source_location (e->goto_locus);
-      e->flags &= ~EDGE_FALLTHRU;
+      if (e->goto_locus && e->goto_block)
+       {
+         set_curr_insn_source_location (e->goto_locus);
+         set_curr_insn_block (e->goto_block);
+         e->goto_locus = curr_insn_locator ();
+       }
+      e->goto_block = NULL;
+      if ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb)
+       {
+         emit_jump (label_rtx_for_bb (e->dest));
+         e->flags &= ~EDGE_FALLTHRU;
+       }
     }
 
   do_pending_stack_adjust ();
@@ -2184,7 +2218,7 @@ static void
 expand_stack_alignment (void)
 {
   rtx drap_rtx;
-  unsigned int preferred_stack_boundary;
+  unsigned int preferred_stack_boundary, incoming_stack_boundary;
 
   if (! SUPPORTS_STACK_ALIGNMENT)
     return;
@@ -2215,8 +2249,15 @@ expand_stack_alignment (void)
   if (preferred_stack_boundary > crtl->stack_alignment_needed)
     crtl->stack_alignment_needed = preferred_stack_boundary;
 
+  /* The incoming stack frame has to be aligned at least at
+     parm_stack_boundary.  */
+  if (crtl->parm_stack_boundary > INCOMING_STACK_BOUNDARY)
+    incoming_stack_boundary = crtl->parm_stack_boundary;
+  else
+    incoming_stack_boundary = INCOMING_STACK_BOUNDARY;
+
   crtl->stack_realign_needed
-    = INCOMING_STACK_BOUNDARY < crtl->stack_alignment_estimated;
+    = incoming_stack_boundary < crtl->stack_alignment_estimated;
   crtl->stack_realign_tried = crtl->stack_realign_needed;
 
   crtl->stack_realign_processed = true;
@@ -2226,6 +2267,9 @@ expand_stack_alignment (void)
   gcc_assert (targetm.calls.get_drap_rtx != NULL);
   drap_rtx = targetm.calls.get_drap_rtx (); 
 
+  /* stack_realign_drap and drap_rtx must match.  */
+  gcc_assert ((stack_realign_drap != 0) == (drap_rtx != NULL));
+
   /* Do nothing if NULL is returned, which means DRAP is not needed.  */
   if (NULL != drap_rtx)
     {
@@ -2261,7 +2305,14 @@ gimple_expand_cfg (void)
 
   insn_locators_alloc ();
   if (!DECL_BUILT_IN (current_function_decl))
-    set_curr_insn_source_location (DECL_SOURCE_LOCATION (current_function_decl));
+    {
+      /* Eventually, all FEs should explicitly set function_start_locus.  */
+      if (cfun->function_start_locus == UNKNOWN_LOCATION)
+       set_curr_insn_source_location
+         (DECL_SOURCE_LOCATION (current_function_decl));
+      else
+       set_curr_insn_source_location (cfun->function_start_locus);
+    }
   set_curr_insn_block (DECL_INITIAL (current_function_decl));
   prologue_locator = curr_insn_locator ();