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]

[tree-ssa] Lowering of VLA's, part 2


Hello,

this patch makes deallocation of stack explicit, thus making vla's as
independent on bind_exprs as any other variable (at least for C
frontend; do other frontends produce them too?  If so, they should
be converted -- it is enough to set them DECL_DEFER_OUTPUT and emit
call to stack_alloc for them, the rest is done automatically).

Zdenek

	* builtins.c (expand_builtin): Expand BUILT_IN_STACK_SAVE and
	BUILT_IN_STACK_RESTORE.
	* builtins.def (BUILT_IN_STACK_SAVE, BUILT_IN_STACK_RESTORE): New.
	* gimplify.c (struct tree_p_list): New type.
	(join_tree_p_list, add_tree_p_list, free_tree_p_list,
	build_stack_save_restore, prepend_to_exit_gotos): New functions.
	(struct gimplify_ctx): New fields current_bind_expr_gotos,
	current_bind_expr_labels and save_stack.
	(push_gimplify_context, pop_gimplify_context): Initialize them.
	(gimple_push_bind_expr, gimple_pop_bind_expr): Update them.
	(gimplify_bind_expr, gimplify_expr, gimplify_call_expr): Arrange save
	of stack on BIND_EXPR entry and restore on exits.
	* stmt.c (expand_stack_alloc): Saving of stack removed.
	(expand_stack_save, expand_stack_restore): New.
	* tree.h (expand_stack_save, expand_stack_restore): Declare.

Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.152.2.31
diff -c -3 -p -r1.152.2.31 builtins.c
*** builtins.c	26 Aug 2003 22:29:33 -0000	1.152.2.31
--- builtins.c	27 Aug 2003 17:31:55 -0000
*************** expand_builtin (tree exp, rtx target, rt
*** 5026,5032 ****
      case BUILT_IN_STACK_ALLOC:
        expand_stack_alloc (TREE_VALUE (arglist),
  			  TREE_VALUE (TREE_CHAIN (arglist)));
!       return NULL_RTX;
  
      case BUILT_IN_FFS:
      case BUILT_IN_FFSL:
--- 5026,5039 ----
      case BUILT_IN_STACK_ALLOC:
        expand_stack_alloc (TREE_VALUE (arglist),
  			  TREE_VALUE (TREE_CHAIN (arglist)));
!       return const0_rtx;
! 
!     case BUILT_IN_STACK_SAVE:
!       return expand_stack_save ();
! 
!     case BUILT_IN_STACK_RESTORE:
!       expand_stack_restore (TREE_VALUE (arglist));
!       return const0_rtx;
  
      case BUILT_IN_FFS:
      case BUILT_IN_FFSL:
Index: builtins.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.def,v
retrieving revision 1.29.2.21
diff -c -3 -p -r1.29.2.21 builtins.def
*** builtins.def	26 Aug 2003 22:29:33 -0000	1.29.2.21
--- builtins.def	27 Aug 2003 17:31:55 -0000
*************** DEF_GCC_BUILTIN        (BUILT_IN_RETURN_
*** 318,323 ****
--- 318,325 ----
  DEF_GCC_BUILTIN        (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, ATTR_NULL)
  DEF_GCC_BUILTIN        (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_NULL)
  DEF_GCC_BUILTIN        (BUILT_IN_STACK_ALLOC, "stack_alloc", BT_FN_VOID_PTR_SIZE, ATTR_NULL)
+ DEF_GCC_BUILTIN        (BUILT_IN_STACK_SAVE, "stack_save", BT_FN_PTR, ATTR_NULL)
+ DEF_GCC_BUILTIN        (BUILT_IN_STACK_RESTORE, "stack_restore", BT_FN_VOID_PTR, ATTR_NULL)
  DEF_GCC_BUILTIN        (BUILT_IN_STDARG_START, "stdarg_start", BT_FN_VOID_VALIST_REF_VAR, ATTR_NULL)
  DEF_EXT_LIB_BUILTIN    (BUILT_IN_STRFMON, "strfmon", BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_3_4)
  DEF_LIB_BUILTIN        (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, ATTR_FORMAT_STRFTIME_3_0)
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimplify.c,v
retrieving revision 1.1.2.74
diff -c -3 -p -r1.1.2.74 gimplify.c
*** gimplify.c	26 Aug 2003 22:21:16 -0000	1.1.2.74
--- gimplify.c	27 Aug 2003 17:32:51 -0000
*************** Software Foundation, 59 Temple Place - S
*** 42,47 ****
--- 42,53 ----
  #include "flags.h"
  #include "real.h"
  
+ struct tree_p_list
+ {
+   tree *elt;
+   struct tree_p_list *next;
+ };
+ 
  static void gimplify_constructor (tree, tree *, tree *);
  static void gimplify_array_ref (tree *, tree *, tree *, int);
  static void gimplify_array_ref_to_plus (tree *, tree *, tree *);
*************** static tree build_addr_expr (tree);
*** 59,65 ****
  static tree build_addr_expr_with_type (tree, tree);
  static tree add_stmt_to_compound (tree, tree);
  static void gimplify_asm_expr (tree, tree *);
! static void gimplify_bind_expr (tree *, tree *);
  static inline void remove_suffix (char *, int);
  static void push_gimplify_context (void);
  static void pop_gimplify_context (void);
--- 65,71 ----
  static tree build_addr_expr_with_type (tree, tree);
  static tree add_stmt_to_compound (tree, tree);
  static void gimplify_asm_expr (tree, tree *);
! static void gimplify_bind_expr (tree *, tree *, tree *);
  static inline void remove_suffix (char *, int);
  static void push_gimplify_context (void);
  static void pop_gimplify_context (void);
*************** static tree gimple_boolify (tree);
*** 89,98 ****
--- 95,113 ----
  static void gimplify_conversion (tree *);
  static int gimplify_init_constructor (tree *, tree *, int);
  static void gimplify_minimax_expr (tree *, tree *, tree *);
+ static void join_tree_p_list (struct tree_p_list **);
+ static void add_tree_p_list (struct tree_p_list **, tree *);
+ static void free_tree_p_list (struct tree_p_list **);
+ static void build_stack_save_restore (tree *, tree *);
+ static void prepend_to_exit_gotos (struct tree_p_list **, struct tree_p_list *,
+ 				   tree);
  
  static struct gimplify_ctx
  {
    tree current_bind_expr;
+   struct tree_p_list *current_bind_expr_gotos;
+   struct tree_p_list *current_bind_expr_labels;
+   bool save_stack;
    tree temps;
    tree conditional_cleanups;
    int conditions;
*************** static struct gimplify_ctx
*** 102,107 ****
--- 117,160 ----
    htab_t temp_htab;
  } *gimplify_ctxp;
  
+ /* Joins two segments of LIST.  */
+ static void
+ join_tree_p_list (struct tree_p_list **list)
+ {
+   struct tree_p_list *act;
+ 
+   while ((*list)->elt)
+     list = &(*list)->next;
+ 
+   act = *list;
+   *list = (*list)->next;
+   free (act);
+ }
+ 
+ /* Adds ELT to the LIST.  */
+ static void
+ add_tree_p_list (struct tree_p_list **list, tree *elt)
+ {
+   struct tree_p_list *nw = xmalloc (sizeof (struct tree_p_list));
+ 
+   nw->elt = elt;
+   nw->next = *list;
+   *list = nw;
+ }
+ 
+ /* Releases the LIST.  */
+ static void
+ free_tree_p_list (struct tree_p_list **list)
+ {
+   struct tree_p_list *next;
+ 
+   for (; *list; *list = next)
+     {
+       next = (*list)->next;
+       free (*list);
+     }
+ }
+ 
  static void
  push_gimplify_context (void)
  {
*************** push_gimplify_context (void)
*** 116,121 ****
--- 169,176 ----
  static void
  pop_gimplify_context (void)
  {
+   struct tree_p_list *l;
+ 
    if (!gimplify_ctxp || gimplify_ctxp->current_bind_expr)
      abort ();
  #if 0
*************** pop_gimplify_context (void)
*** 124,129 ****
--- 179,192 ----
  	     htab_collisions (gimplify_ctxp->temp_htab));
  #endif
    htab_delete (gimplify_ctxp->temp_htab);
+ 
+   free_tree_p_list (&gimplify_ctxp->current_bind_expr_gotos);
+   /* Reset DECL_TOO_LATE for the labels, so that it is ready for use in
+      tree->rtl expansion.  */
+   for (l = gimplify_ctxp->current_bind_expr_labels; l; l = l->next)
+     if (l->elt)
+       DECL_TOO_LATE (*l->elt) = 0;
+   free_tree_p_list (&gimplify_ctxp->current_bind_expr_labels);
    free (gimplify_ctxp);
    gimplify_ctxp = NULL;
  }
*************** gimple_push_bind_expr (tree bind)
*** 133,138 ****
--- 196,205 ----
  {
    TREE_CHAIN (bind) = gimplify_ctxp->current_bind_expr;
    gimplify_ctxp->current_bind_expr = bind;
+ 
+   /* Separate the records of gotos and labels in the bind exprs.  */
+   add_tree_p_list (&gimplify_ctxp->current_bind_expr_gotos, NULL);
+   add_tree_p_list (&gimplify_ctxp->current_bind_expr_labels, NULL);
  }
  
  void
*************** gimple_pop_bind_expr (void)
*** 140,145 ****
--- 207,216 ----
  {
    gimplify_ctxp->current_bind_expr
      = TREE_CHAIN (gimplify_ctxp->current_bind_expr);
+ 
+   /* Add the list of gotos and labels to the outer list.  */
+   join_tree_p_list (&gimplify_ctxp->current_bind_expr_gotos);
+   join_tree_p_list (&gimplify_ctxp->current_bind_expr_labels);
  }
  
  tree
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 512,518 ****
  	  break;
  
  	case BIND_EXPR:
! 	  gimplify_bind_expr (expr_p, pre_p);
  	  break;
  
  	case LOOP_EXPR:
--- 583,589 ----
  	  break;
  
  	case BIND_EXPR:
! 	  gimplify_bind_expr (expr_p, pre_p, post_p);
  	  break;
  
  	case LOOP_EXPR:
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 556,565 ****
--- 627,649 ----
  		FUNCTION_RECEIVES_NONLOCAL_GOTO (context) = 1;
  	      }
  
+ 	    if (TREE_CODE (dest) == LABEL_DECL)
+ 	      {
+ 		add_tree_p_list (&gimplify_ctxp->current_bind_expr_gotos,
+ 				 expr_p);
+ 
+ 		/* If we jump to a label with DECL_TOO_LATE, this is an
+ 		   error.  */
+ 		if (DECL_TOO_LATE (dest))
+ 		  error ("jump to `%s' invalidly jumps into binding contour",
+ 			 IDENTIFIER_POINTER (DECL_NAME (dest)));
+ 	      }
  	    break;
  	  }
  
  	case LABEL_EXPR:
+ 	  add_tree_p_list (&gimplify_ctxp->current_bind_expr_labels,
+ 			   &LABEL_EXPR_LABEL (*expr_p));
  	  break;
  
  	case CASE_LABEL_EXPR:
*************** voidify_wrapper_expr (tree wrapper)
*** 875,887 ****
  /* Gimplify a BIND_EXPR.  Just voidify and recurse.  */
  
  static void
! gimplify_bind_expr (tree *expr_p, tree *pre_p)
  {
    tree bind_expr = *expr_p;
    tree temp = voidify_wrapper_expr (bind_expr);
  
    gimple_push_bind_expr (bind_expr);
    gimplify_stmt (&BIND_EXPR_BODY (bind_expr));
    gimple_pop_bind_expr ();
  
    if (temp)
--- 959,990 ----
  /* Gimplify a BIND_EXPR.  Just voidify and recurse.  */
  
  static void
! gimplify_bind_expr (tree *expr_p, tree *pre_p, tree *post_p)
  {
    tree bind_expr = *expr_p;
    tree temp = voidify_wrapper_expr (bind_expr);
+   bool old_save_stack = gimplify_ctxp->save_stack;
  
    gimple_push_bind_expr (bind_expr);
+   gimplify_ctxp->save_stack = false;
+ 
    gimplify_stmt (&BIND_EXPR_BODY (bind_expr));
+   if (gimplify_ctxp->save_stack)
+     {
+       tree stack_save, stack_restore;
+ 
+       /* Save stack on entry and restore it on exit.  Also add restores
+ 	 to exits through gotos.  */
+       build_stack_save_restore (&stack_save, &stack_restore); 
+       add_tree (stack_save, pre_p);
+       add_tree (stack_restore, post_p);
+ 
+       prepend_to_exit_gotos (&gimplify_ctxp->current_bind_expr_gotos,
+ 			     gimplify_ctxp->current_bind_expr_labels,
+ 			     stack_restore);
+     }
+ 
+   gimplify_ctxp->save_stack = old_save_stack;
    gimple_pop_bind_expr ();
  
    if (temp)
*************** gimplify_call_expr (tree *expr_p, tree *
*** 1584,1589 ****
--- 1687,1697 ----
  	  return;
  	}
  
+       /* If it is allocation of stack, record the need to restore the memory
+ 	 when the enclosing bind_expr is exited.  */
+       if (DECL_FUNCTION_CODE (decl) == BUILT_IN_STACK_ALLOC)
+ 	gimplify_ctxp->save_stack = true;
+ 
        new = simplify_builtin (*expr_p, gimple_test_f == is_gimple_stmt);
  
        if (new && new != *expr_p)
*************** gimplify_target_expr (tree *expr_p, tree
*** 2930,2933 ****
--- 3038,3136 ----
      }
  
    *expr_p = temp;
+ }
+ 
+ /* Prepare calls to builtins to SAVE and RESTORE the stack as well as temporary
+    through that they comunicate.  */
+ static void
+ build_stack_save_restore (tree *save, tree *restore)
+ {
+   tree save_call, tmp_var;
+ 
+   save_call = build_function_call_expr (
+ 			implicit_built_in_decls[BUILT_IN_STACK_SAVE],
+ 			NULL_TREE);
+   tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
+ 
+   *save = build (MODIFY_EXPR, ptr_type_node, tmp_var, save_call);
+   *restore = build_function_call_expr (
+ 			implicit_built_in_decls[BUILT_IN_STACK_RESTORE],
+ 			tree_cons (NULL_TREE, tmp_var, NULL_TREE));
+ }
+ 
+ /* Prepends copy of statement STMT to gotos from list GOTOS that lead
+    to labels not in list LABELS.  */
+ static void
+ prepend_to_exit_gotos (struct tree_p_list **gotos, struct tree_p_list *labels,
+ 		       tree stmt)
+ {
+   htab_t labels_t;
+   struct tree_p_list *act;
+ 
+   labels_t = htab_create (10, htab_hash_pointer, htab_eq_pointer, NULL);
+ 
+   /* Prepare a hash table of labels.  */
+   for (; labels->elt; labels = labels->next)
+     {
+       void **slot = htab_find_slot (labels_t, *labels->elt, INSERT);
+ 
+       /* Mark the label so that we may issue errors for gotos into this
+ 	 bind_expr.  */
+       DECL_TOO_LATE (*labels->elt) = 1;
+ 
+       if (!*slot)
+ 	*slot = *labels->elt;
+     }
+ 
+   for (; (*gotos)->elt; )
+     {
+       tree insert;
+       tree *elt = (*gotos)->elt;
+       void *lab = htab_find (labels_t, GOTO_DESTINATION (*elt));
+ 
+       if (lab)
+ 	{
+ 	  /* The goto is local from this bind_expr up, so remove it so that
+ 	     it is not processed unnecesarily later.  */	  
+ 	  act = *gotos;
+ 	  *gotos = (*gotos)->next;
+ 	  free (act);
+ 	  continue;
+ 	}
+ 
+       insert = unshare_expr (stmt);
+ 
+       /* Since we don't know the goto_expr's container, prepending the
+ 	 statement involves creating a bind_expr wrapper.  */
+       *elt = build (BIND_EXPR, void_type_node, NULL_TREE,
+ 		    build (COMPOUND_EXPR, void_type_node,
+ 			   insert,
+ 			   *elt),
+ 		    NULL_TREE);
+       recalculate_side_effects (*elt);
+ 
+       /* Make the gotos->elt point to goto statement again so that outer
+ 	 bind_exprs that it might exit are happy.  */
+       (*gotos)->elt = &TREE_OPERAND (BIND_EXPR_BODY (*elt), 1);
+       gotos = &(*gotos)->next;
+     }
+ 
+   /* Go through all the remaining goto_exprs in the list and check whether
+      they jump to one of lables inside this bind_expr.  If they do, it is
+      an error.  */
+   for (; *gotos; gotos = &(*gotos)->next)
+     {
+       tree *elt = (*gotos)->elt;
+       void *lab;
+ 
+       if (!elt)
+ 	continue;
+       lab = htab_find (labels_t, GOTO_DESTINATION (*elt));
+ 
+       if (lab)
+ 	error ("jump to `%s' invalidly jumps into binding contour",
+ 	       IDENTIFIER_POINTER (DECL_NAME (GOTO_DESTINATION (*elt))));
+     }
+ 
+   htab_delete (labels_t);
  }
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.267.2.28
diff -c -3 -p -r1.267.2.28 stmt.c
*** stmt.c	26 Aug 2003 22:29:34 -0000	1.267.2.28
--- stmt.c	27 Aug 2003 17:33:35 -0000
*************** expand_stack_alloc (tree alloc, tree t_s
*** 4059,4069 ****
  
    type = TREE_TYPE (var);
  
-   /* Record the stack pointer on entry to block, if have
-      not already done so.  */
-   do_pending_stack_adjust ();
-   save_stack_pointer ();
- 
    /* In function-at-a-time mode, variable_size doesn't expand this,
       so do it now.  */
    if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
--- 4025,4030 ----
*************** expand_stack_alloc (tree alloc, tree t_s
*** 4087,4092 ****
--- 4048,4073 ----
    DECL_ALIGN (var) = BIGGEST_ALIGNMENT;
  #endif
    DECL_USER_ALIGN (var) = 0;
+ }
+ 
+ /* Emit code to save the current value of stack.  */
+ rtx
+ expand_stack_save ()
+ {
+   rtx ret = NULL_RTX;
+ 
+   do_pending_stack_adjust ();
+   emit_stack_save (SAVE_BLOCK, &ret, NULL_RTX);
+   return ret;
+ }
+ 
+ /* Emit code to restore the current value of stack.  */
+ void
+ expand_stack_restore (tree var)
+ {
+   rtx sa = DECL_RTL (var);
+ 
+   emit_stack_restore (SAVE_BLOCK, sa, NULL_RTX);
  }
  
  /* Emit code to perform the initialization of a declaration DECL.  */
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.91
diff -c -3 -p -r1.342.2.91 tree.h
*** tree.h	27 Aug 2003 04:31:36 -0000	1.342.2.91
--- tree.h	27 Aug 2003 17:42:05 -0000
*************** extern int expand_exit_loop_top_cond (st
*** 3093,3098 ****
--- 3093,3100 ----
  extern int expand_exit_something (void);
  
  extern void expand_stack_alloc (tree, tree);
+ extern rtx expand_stack_save (void);
+ extern void expand_stack_restore (tree);
  extern void expand_return (tree);
  extern int optimize_tail_recursion (tree, rtx);
  extern void expand_start_bindings_and_block (int, tree);


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