This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix stack overflow problem when bootstrapping on Darwin


If you have a long chain of code like:

    ...
    goto L20;
L1: ...
    goto L21;
L2: ...

then what happens is that expand_stmt, when it hits each 'goto', calls
expand_unreachable_stmt, which promptly notices the label, which calls
back to expand_stmt.  After this happens a few thousand times, as in
insn-recog.c, the stack overflows.  Some of these would be sibcalls,
which would help a lot, except that the stage1 compiler is built using
-O0 and so not only are there no sibcalls but the stack frames are
unusually inflated.

So, this rearranges expand_unreachable_stmt so that it's usually just
a subroutine of expand_stmt; it processes only the unreachable insns,
and then returns to let expand_stmt finish up.

I don't think this is necessary for 3.3 since it happens only while
bootstrapping and 3.4 has a significantly more complicated insn-recog.c.

Bootstrapped & tested on powerpc-darwin.

-- 
- Geoffrey Keating <geoffk@apple.com>

===File ~/patches/gcc-unreachablestkoverflow.patch==========
2003-04-29  Geoffrey Keating  <geoffk@apple.com>

	* c-semantics.c (expand_unreachable_stmt): Return a tree.
	(expand_stmt): Update for change to expand_unreachable_stmt.
	(expand_unreachable_if_stmt): Likewise.

Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-semantics.c,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 c-semantics.c
--- c-semantics.c	20 Apr 2003 22:58:28 -0000	1.55
+++ c-semantics.c	29 Apr 2003 20:36:59 -0000
@@ -55,7 +55,7 @@ void (*lang_expand_decl_stmt) PARAMS ((t
 static tree find_reachable_label_1	PARAMS ((tree *, int *, void *));
 static tree find_reachable_label	PARAMS ((tree));
 static bool expand_unreachable_if_stmt	PARAMS ((tree));
-static bool expand_unreachable_stmt	PARAMS ((tree, int));
+static tree expand_unreachable_stmt	PARAMS ((tree, int));
 
 /* Create an empty statement tree rooted at T.  */
 
@@ -823,8 +823,8 @@ expand_stmt (t)
 
 	case RETURN_STMT:
 	  genrtl_return_stmt (t);
-	  expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
-	  return;
+	  t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
+	  goto process_t;
 
 	case EXPR_STMT:
 	  genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t),
@@ -859,13 +859,13 @@ expand_stmt (t)
 
 	case BREAK_STMT:
 	  genrtl_break_stmt ();
-	  expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
-	  return;
+	  t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
+	  goto process_t;
 
 	case CONTINUE_STMT:
 	  genrtl_continue_stmt ();
-	  expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
-	  return;
+	  t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
+	  goto process_t;
 
 	case SWITCH_STMT:
 	  genrtl_switch_stmt (t);
@@ -890,8 +890,8 @@ expand_stmt (t)
 	      NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_GOTO, NOT_TAKEN);
 	    }
 	  genrtl_goto_stmt (GOTO_DESTINATION (t));
-	  expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
-	  return;
+	  t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
+	  goto process_t;
 
 	case ASM_STMT:
 	  genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
@@ -915,12 +915,13 @@ expand_stmt (t)
 	  break;
 	}
 
+      /* Go on to the next statement in this scope.  */
+      t = TREE_CHAIN (t);
+
+    process_t:
       /* Restore saved state.  */
       current_stmt_tree ()->stmts_are_full_exprs_p
 	= saved_stmts_are_full_exprs_p;
-
-      /* Go on to the next statement in this scope.  */
-      t = TREE_CHAIN (t);
     }
 }
 
@@ -964,6 +965,8 @@ static bool
 expand_unreachable_if_stmt (t)
      tree t;
 {
+  tree n;
+  
   if (find_reachable_label (IF_COND (t)) != NULL_TREE)
     {
       genrtl_if_stmt (t);
@@ -972,31 +975,38 @@ expand_unreachable_if_stmt (t)
 
   if (THEN_CLAUSE (t) && ELSE_CLAUSE (t))
     {
-      if (expand_unreachable_stmt (THEN_CLAUSE (t), 0))
+      n = expand_unreachable_stmt (THEN_CLAUSE (t), 0);
+      
+      if (n != NULL_TREE)
 	{
 	  rtx label;
+	  expand_stmt (n);
 	  label = gen_label_rtx ();
 	  emit_jump (label);
-	  expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
+	  expand_stmt (expand_unreachable_stmt (ELSE_CLAUSE (t), 0));
 	  emit_label (label);
 	  return true;
 	}
       else
-	return expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
+	n = expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
     }
   else if (THEN_CLAUSE (t))
-    return expand_unreachable_stmt (THEN_CLAUSE (t), 0);
+    n = expand_unreachable_stmt (THEN_CLAUSE (t), 0);
   else if (ELSE_CLAUSE (t))
-    return expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
-
-  return false;
+    n = expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
+  else
+    n = NULL_TREE;
+  
+  expand_stmt (n);
+  
+  return n != NULL_TREE;
 }
 
 /* Expand an unreachable statement list.  This function skips all
    statements preceding the first potentially reachable label and
-   then expands the statements normally with expand_stmt.  This
-   function returns true if such a reachable label was found.  */
-static bool
+   then returns the label (or, in same cases, the statement after
+   one containing the label).  */
+static tree
 expand_unreachable_stmt (t, warn)
      tree t;
      int warn;
@@ -1037,36 +1047,31 @@ expand_unreachable_stmt (t, warn)
 
 	case RETURN_STMT:
 	  if (find_reachable_label (RETURN_STMT_EXPR (t)) != NULL_TREE)
-	    {
-	      expand_stmt (t);
-	      return true;
-	    }
+	    return t;
 	  break;
 
 	case EXPR_STMT:
 	  if (find_reachable_label (EXPR_STMT_EXPR (t)) != NULL_TREE)
-	    {
-	      expand_stmt (t);
-	      return true;
-	    }
+	    return t;
 	  break;
 
 	case IF_STMT:
 	  if (expand_unreachable_if_stmt (t))
-	    {
-	      expand_stmt (TREE_CHAIN (t));
-	      return true;
-	    }
+	    return TREE_CHAIN (t);
 	  break;
 
 	case COMPOUND_STMT:
-	  if (expand_unreachable_stmt (COMPOUND_BODY (t), warn))
-	    {
-	      expand_stmt (TREE_CHAIN (t));
-	      return true;
-	    }
-	  warn = false;
-	  break;
+	  {
+	    tree n;
+	    n = expand_unreachable_stmt (COMPOUND_BODY (t), warn);
+	    if (n != NULL_TREE)
+	      {
+		expand_stmt (n);
+		return TREE_CHAIN (t);
+	      }
+	    warn = false;
+	    break;
+	  }
 
 	case SCOPE_STMT:
 	  saved = stmts_are_full_exprs_p ();
@@ -1076,11 +1081,10 @@ expand_unreachable_stmt (t, warn)
 	  break;
 
 	default:
-	  expand_stmt (t);
-	  return true;
+	  return t;
 	}
       t = TREE_CHAIN (t);
     }
-  return false;
+  return NULL_TREE;
 }
 
============================================================


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]