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]

Lower VLA representation to pointers


This should fix the problem discovered by the Ada front end wrt
the loop optimizer.  Wherein we lied about the const-ness of &vla,
and the loop optimizer decided to move the code advertized to be
outside of the loop.

Now, given

	int xyzzy[n];
	xyzzy[i] = 0;

we'll generate

	T.2 = __builtin_alloca (size);
	xyzzy.1 = (int [] *)T.2
	(*xyzzy.1)[i] = 0;

We'll also arrange for the debug info to come out correct, such
that you can still ask about "xyzzy" and get correct results,
both type-wise and value-wise.

Bootstrapped and tested on i686-linux, without Ada since there are
a number of known outstanding problems there still.


r~


        * builtins.def (BUILT_IN_STACK_ALLOC): Remove.
        * builtins.c (expand_builtin) <BUILT_IN_STACK_ALLOC>: Remove.
        * dwarf2out.c (loc_descriptor): Handle PARALLEL here ...
        (add_location_or_const_value_attribute): ... not here.  Use
        loc_descriptor_from_tree if possible.
        (loc_descriptor_from_tree_1): Rename from loc_descriptor_from_tree.
        Simplify address handling.  Handle DECL_VALUE_EXPR.  Handle register
        values specially.
        (loc_descriptor_from_tree): New.  Update callers.
        * expr.c (expand_var): Ignore DECL_VALUE_EXPR variables.
        * gimplify.c (gimplify_decl_expr): Lower variable sized types to
        pointer plus dereference.  Set DECL_VALUE_EXPR.  Set save_stack.
        (gimplify_call_expr): Do not recognize BUILT_IN_STACK_ALLOC
        and BUILT_IN_STACK_RESTORE.
        (gimplify_expr): Lower DECL_VALUE_EXPR decls.
        * stmt.c (expand_stack_alloc): Remove.
        * tree-mudflap.c (mx_register_decls): Don't look for
        BUILT_IN_STACK_ALLOC.
        * tree-nested.c (convert_local_reference): Likewise.
        * tree.h (DECL_VALUE_EXPR): New.
ada/
        * utils.c (gnat_install_builtins): Remove __builtin_stack_alloc,
        add __builtin_alloca.
fortran/
        * f95-lang.c (gfc_init_builtin_functions): Remove
         __builtin_stack_alloc, add __builtin_alloca.
        * trans-array.c (gfc_trans_auto_array_allocation): Use DECL_EXPR.
        * trans-decl.c (gfc_trans_auto_character_variable): Likewise.

Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.370
diff -c -p -d -r1.370 builtins.c
*** builtins.c	25 Jul 2004 23:26:59 -0000	1.370
--- builtins.c	11 Aug 2004 04:00:16 -0000
*************** expand_builtin (tree exp, rtx target, rt
*** 5756,5766 ****
  	return target;
        break;
  
-     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 ();
  
--- 5756,5761 ----
Index: builtins.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.def,v
retrieving revision 1.88
diff -c -p -d -r1.88 builtins.def
*** builtins.def	9 Jul 2004 23:04:32 -0000	1.88
--- builtins.def	11 Aug 2004 04:00:16 -0000
*************** DEF_GCC_BUILTIN        (BUILT_IN_RETURN,
*** 607,613 ****
  DEF_GCC_BUILTIN        (BUILT_IN_RETURN_ADDRESS, "return_address", BT_FN_PTR_UINT, ATTR_NULL)
  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)
--- 607,612 ----
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.539
diff -c -p -d -r1.539 dwarf2out.c
*** dwarf2out.c	3 Aug 2004 00:52:18 -0000	1.539
--- dwarf2out.c	11 Aug 2004 04:00:17 -0000
*************** static int is_based_loc (rtx);
*** 3907,3913 ****
  static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode, bool);
  static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx);
  static dw_loc_descr_ref loc_descriptor (rtx, bool);
! static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
  static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
  static tree field_type (tree);
  static unsigned int simple_type_align_in_bits (tree);
--- 3907,3914 ----
  static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode, bool);
  static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx);
  static dw_loc_descr_ref loc_descriptor (rtx, bool);
! static dw_loc_descr_ref loc_descriptor_from_tree_1 (tree, int);
! static dw_loc_descr_ref loc_descriptor_from_tree (tree);
  static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
  static tree field_type (tree);
  static unsigned int simple_type_align_in_bits (tree);
*************** loc_descriptor (rtx rtl, bool can_use_fb
*** 8805,8838 ****
        if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
  	{
  	  loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), can_use_fbreg);
  	}
-       /* Multiple parts.  */
-       else
- 	{
- 	  rtvec par_elems = XVEC (XEXP (rtl, 1), 0);
- 	  int num_elem = GET_NUM_ELEM (par_elems);
- 	  enum machine_mode mode;
- 	  int i;
  
! 	  /* Create the first one, so we have something to add to.  */
! 	  loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
! 				       can_use_fbreg);
! 	  mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
! 	  add_loc_descr (&loc_result,
! 			 new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
! 	  for (i = 1; i < num_elem; i++)
! 	    {
! 	      dw_loc_descr_ref temp;
  
! 	      temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0),
  				     can_use_fbreg);
! 	      add_loc_descr (&loc_result, temp);
! 	      mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
! 	      add_loc_descr (&loc_result,
! 			     new_loc_descr (DW_OP_piece,
! 					    GET_MODE_SIZE (mode), 0));
! 	    }
! 	}
        break;
  
      default:
--- 8806,8843 ----
        if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
  	{
  	  loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), can_use_fbreg);
+ 	  break;
  	}
  
!       rtl = XEXP (rtl, 1);
!       /* FALLTHRU */
  
!     case PARALLEL:
!       {
! 	rtvec par_elems = XVEC (rtl, 0);
! 	int num_elem = GET_NUM_ELEM (par_elems);
! 	enum machine_mode mode;
! 	int i;
! 
! 	/* Create the first one, so we have something to add to.  */
! 	loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
  				     can_use_fbreg);
! 	mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
! 	add_loc_descr (&loc_result,
! 		       new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
! 	for (i = 1; i < num_elem; i++)
! 	  {
! 	    dw_loc_descr_ref temp;
! 
! 	    temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0),
! 				   can_use_fbreg);
! 	    add_loc_descr (&loc_result, temp);
! 	    mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
! 	    add_loc_descr (&loc_result,
! 			   new_loc_descr (DW_OP_piece,
! 					  GET_MODE_SIZE (mode), 0));
! 	  }
!       }
        break;
  
      default:
*************** loc_descriptor (rtx rtl, bool can_use_fb
*** 8843,8857 ****
  }
  
  /* Similar, but generate the descriptor from trees instead of rtl.  This comes
!    up particularly with variable length arrays.  If ADDRESSP is nonzero, we are
!    looking for an address.  Otherwise, we return a value.  If we can't make a
!    descriptor, return 0.  */
  
  static dw_loc_descr_ref
! loc_descriptor_from_tree (tree loc, int addressp)
  {
    dw_loc_descr_ref ret, ret1;
!   int indirect_p = 0;
    int unsignedp = TYPE_UNSIGNED (TREE_TYPE (loc));
    enum dwarf_location_atom op;
  
--- 8848,8863 ----
  }
  
  /* Similar, but generate the descriptor from trees instead of rtl.  This comes
!    up particularly with variable length arrays.  WANT_ADDRESS is 2 if this is
!    a top-level invocation of loc_descriptor_from_tree; is 1 if this is not a
!    top-level invocation, and we require the address of LOC; is 0 if we require
!    the value of LOC.  */
  
  static dw_loc_descr_ref
! loc_descriptor_from_tree_1 (tree loc, int want_address)
  {
    dw_loc_descr_ref ret, ret1;
!   int have_address = 0;
    int unsignedp = TYPE_UNSIGNED (TREE_TYPE (loc));
    enum dwarf_location_atom op;
  
*************** loc_descriptor_from_tree (tree loc, int 
*** 8882,8900 ****
        return 0;
  
      case ADDR_EXPR:
!       /* We can support this only if we can look through conversions and
! 	 find an INDIRECT_EXPR.  */
!       for (loc = TREE_OPERAND (loc, 0);
! 	   TREE_CODE (loc) == CONVERT_EXPR || TREE_CODE (loc) == NOP_EXPR
! 	   || TREE_CODE (loc) == NON_LVALUE_EXPR
! 	   || TREE_CODE (loc) == VIEW_CONVERT_EXPR
! 	   || TREE_CODE (loc) == SAVE_EXPR;
! 	   loc = TREE_OPERAND (loc, 0))
! 	;
  
!        return (TREE_CODE (loc) == INDIRECT_REF
! 	       ? loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp)
! 	       : 0);
  
      case VAR_DECL:
        if (DECL_THREAD_LOCAL (loc))
--- 8888,8899 ----
        return 0;
  
      case ADDR_EXPR:
!       /* If we already want an address, there's nothing we can do.  */
!       if (want_address)
! 	return 0;
  
!       /* Otherwise, process the argument and look for the address.  */
!       return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 1);
  
      case VAR_DECL:
        if (DECL_THREAD_LOCAL (loc))
*************** loc_descriptor_from_tree (tree loc, int 
*** 8928,8974 ****
  	  ret1 = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
  	  add_loc_descr (&ret, ret1);
  
! 	  indirect_p = 1;
  	  break;
  	}
!       /* Fall through.  */
  
      case PARM_DECL:
      case RESULT_DECL:
        {
  	rtx rtl = rtl_for_decl_location (loc);
  
  	if (rtl == NULL_RTX)
  	  return 0;
  	else if (CONSTANT_P (rtl))
  	  {
  	    ret = new_loc_descr (DW_OP_addr, 0, 0);
  	    ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
  	    ret->dw_loc_oprnd1.v.val_addr = rtl;
- 	    indirect_p = 1;
  	  }
  	else
  	  {
! 	    enum machine_mode mode = GET_MODE (rtl);
  
  	    if (MEM_P (rtl))
  	      {
- 		indirect_p = 1;
  		rtl = XEXP (rtl, 0);
  	      }
- 
  	    ret = mem_loc_descriptor (rtl, mode, true);
  	  }
        }
        break;
  
      case INDIRECT_REF:
!       ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
!       indirect_p = 1;
        break;
  
      case COMPOUND_EXPR:
!       return loc_descriptor_from_tree (TREE_OPERAND (loc, 1), addressp);
  
      case NOP_EXPR:
      case CONVERT_EXPR:
--- 8927,8989 ----
  	  ret1 = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
  	  add_loc_descr (&ret, ret1);
  
! 	  have_address = 1;
  	  break;
  	}
!       /* FALLTHRU */
  
      case PARM_DECL:
+       if (DECL_VALUE_EXPR (loc))
+ 	return loc_descriptor_from_tree_1 (DECL_VALUE_EXPR (loc), want_address);
+       /* FALLTHRU */
+ 
      case RESULT_DECL:
        {
  	rtx rtl = rtl_for_decl_location (loc);
  
  	if (rtl == NULL_RTX)
  	  return 0;
+         else if (GET_CODE (rtl) == CONST_INT)
+ 	  {
+ 	    HOST_WIDE_INT val = INTVAL (rtl);
+ 	    if (TYPE_UNSIGNED (TREE_TYPE (loc)))
+ 	      val &= GET_MODE_MASK (DECL_MODE (loc));
+ 	    ret = int_loc_descriptor (val);
+ 	  }
+ 	else if (GET_CODE (rtl) == CONST_STRING)
+ 	  return 0;
  	else if (CONSTANT_P (rtl))
  	  {
  	    ret = new_loc_descr (DW_OP_addr, 0, 0);
  	    ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
  	    ret->dw_loc_oprnd1.v.val_addr = rtl;
  	  }
  	else
  	  {
! 	    enum machine_mode mode;
  
+ 	    /* Certain constructs can only be represented at top-level.  */
+ 	    if (want_address == 2)
+ 	      return loc_descriptor (rtl, true);
+ 
+ 	    mode = GET_MODE (rtl);
  	    if (MEM_P (rtl))
  	      {
  		rtl = XEXP (rtl, 0);
+ 		have_address = 1;
  	      }
  	    ret = mem_loc_descriptor (rtl, mode, true);
  	  }
        }
        break;
  
      case INDIRECT_REF:
!       ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
!       have_address = 1;
        break;
  
      case COMPOUND_EXPR:
!       return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), want_address);
  
      case NOP_EXPR:
      case CONVERT_EXPR:
*************** loc_descriptor_from_tree (tree loc, int 
*** 8976,8982 ****
      case VIEW_CONVERT_EXPR:
      case SAVE_EXPR:
      case MODIFY_EXPR:
!       return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp);
  
      case COMPONENT_REF:
      case BIT_FIELD_REF:
--- 8991,8997 ----
      case VIEW_CONVERT_EXPR:
      case SAVE_EXPR:
      case MODIFY_EXPR:
!       return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), want_address);
  
      case COMPONENT_REF:
      case BIT_FIELD_REF:
*************** loc_descriptor_from_tree (tree loc, int 
*** 8994,9000 ****
  	if (obj == loc)
  	  return 0;
  
! 	ret = loc_descriptor_from_tree (obj, 1);
  	if (ret == 0
  	    || bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
  	  return 0;
--- 9009,9015 ----
  	if (obj == loc)
  	  return 0;
  
! 	ret = loc_descriptor_from_tree_1 (obj, 1);
  	if (ret == 0
  	    || bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
  	  return 0;
*************** loc_descriptor_from_tree (tree loc, int 
*** 9002,9014 ****
  	if (offset != NULL_TREE)
  	  {
  	    /* Variable offset.  */
! 	    add_loc_descr (&ret, loc_descriptor_from_tree (offset, 0));
  	    add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
  	  }
  
- 	if (!addressp)
- 	  indirect_p = 1;
- 
  	bytepos = bitpos / BITS_PER_UNIT;
  	if (bytepos > 0)
  	  add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0));
--- 9017,9026 ----
  	if (offset != NULL_TREE)
  	  {
  	    /* Variable offset.  */
! 	    add_loc_descr (&ret, loc_descriptor_from_tree_1 (offset, 0));
  	    add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
  	  }
  
  	bytepos = bitpos / BITS_PER_UNIT;
  	if (bytepos > 0)
  	  add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0));
*************** loc_descriptor_from_tree (tree loc, int 
*** 9017,9022 ****
--- 9029,9036 ----
  	    add_loc_descr (&ret, int_loc_descriptor (bytepos));
  	    add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
  	  }
+ 
+ 	have_address = 1;
  	break;
        }
  
*************** loc_descriptor_from_tree (tree loc, int 
*** 9033,9047 ****
  	rtx rtl = lookup_constant_def (loc);
  	enum machine_mode mode;
  
! 	if (!MEM_P (rtl))
  	  return 0;
  	mode = GET_MODE (rtl);
  	rtl = XEXP (rtl, 0);
- 
- 	rtl = targetm.delegitimize_address (rtl);
- 
- 	indirect_p = 1;
  	ret = mem_loc_descriptor (rtl, mode, true);
  	break;
        }
  
--- 9047,9058 ----
  	rtx rtl = lookup_constant_def (loc);
  	enum machine_mode mode;
  
! 	if (!rtl || !MEM_P (rtl))
  	  return 0;
  	mode = GET_MODE (rtl);
  	rtl = XEXP (rtl, 0);
  	ret = mem_loc_descriptor (rtl, mode, true);
+ 	have_address = 1;
  	break;
        }
  
*************** loc_descriptor_from_tree (tree loc, int 
*** 9096,9102 ****
        if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
  	  && host_integerp (TREE_OPERAND (loc, 1), 0))
  	{
! 	  ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
  	  if (ret == 0)
  	    return 0;
  
--- 9107,9113 ----
        if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
  	  && host_integerp (TREE_OPERAND (loc, 1), 0))
  	{
! 	  ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
  	  if (ret == 0)
  	    return 0;
  
*************** loc_descriptor_from_tree (tree loc, int 
*** 9148,9155 ****
        goto do_binop;
  
      do_binop:
!       ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
!       ret1 = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
        if (ret == 0 || ret1 == 0)
  	return 0;
  
--- 9159,9166 ----
        goto do_binop;
  
      do_binop:
!       ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
!       ret1 = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0);
        if (ret == 0 || ret1 == 0)
  	return 0;
  
*************** loc_descriptor_from_tree (tree loc, int 
*** 9171,9177 ****
        goto do_unop;
  
      do_unop:
!       ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
        if (ret == 0)
  	return 0;
  
--- 9182,9188 ----
        goto do_unop;
  
      do_unop:
!       ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
        if (ret == 0)
  	return 0;
  
*************** loc_descriptor_from_tree (tree loc, int 
*** 9187,9193 ****
          loc = build3 (COND_EXPR, TREE_TYPE (loc),
  		      build2 (code, integer_type_node,
  			      TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
!                      TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
        }
  
        /* ... fall through ...  */
--- 9198,9204 ----
          loc = build3 (COND_EXPR, TREE_TYPE (loc),
  		      build2 (code, integer_type_node,
  			      TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
!                       TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
        }
  
        /* ... fall through ...  */
*************** loc_descriptor_from_tree (tree loc, int 
*** 9195,9206 ****
      case COND_EXPR:
        {
  	dw_loc_descr_ref lhs
! 	  = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
  	dw_loc_descr_ref rhs
! 	  = loc_descriptor_from_tree (TREE_OPERAND (loc, 2), 0);
  	dw_loc_descr_ref bra_node, jump_node, tmp;
  
! 	ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
  	if (ret == 0 || lhs == 0 || rhs == 0)
  	  return 0;
  
--- 9206,9217 ----
      case COND_EXPR:
        {
  	dw_loc_descr_ref lhs
! 	  = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0);
  	dw_loc_descr_ref rhs
! 	  = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 2), 0);
  	dw_loc_descr_ref bra_node, jump_node, tmp;
  
! 	ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
  	if (ret == 0 || lhs == 0 || rhs == 0)
  	  return 0;
  
*************** loc_descriptor_from_tree (tree loc, int 
*** 9236,9246 ****
      }
  
    /* Show if we can't fill the request for an address.  */
!   if (addressp && indirect_p == 0)
      return 0;
  
    /* If we've got an address and don't want one, dereference.  */
!   if (!addressp && indirect_p > 0)
      {
        HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
  
--- 9247,9257 ----
      }
  
    /* Show if we can't fill the request for an address.  */
!   if (want_address && !have_address)
      return 0;
  
    /* If we've got an address and don't want one, dereference.  */
!   if (!want_address && have_address)
      {
        HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
  
*************** loc_descriptor_from_tree (tree loc, int 
*** 9257,9262 ****
--- 9268,9279 ----
    return ret;
  }
  
+ static inline dw_loc_descr_ref
+ loc_descriptor_from_tree (tree loc)
+ {
+   return loc_descriptor_from_tree_1 (loc, 2);
+ }
+ 
  /* Given a value, round it up to the lowest multiple of `boundary'
     which is not less than the value itself.  */
  
*************** add_location_or_const_value_attribute (d
*** 10072,10143 ****
      }
  
    rtl = rtl_for_decl_location (decl);
!   if (rtl == NULL_RTX)
!     return;
! 
!   switch (GET_CODE (rtl))
      {
-     case CONST_INT:
-     case CONST_DOUBLE:
-     case CONST_VECTOR:
-     case CONST_STRING:
-     case SYMBOL_REF:
-     case LABEL_REF:
-     case CONST:
-     case PLUS:
-       /* DECL_RTL could be (plus (reg ...) (const_int ...)) */
        add_const_value_attribute (die, rtl);
!       break;
! 
!     case MEM:
!       if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
! 	{
! 	  /* Need loc_descriptor_from_tree since that's where we know
! 	     how to handle TLS variables.  Want the object's address
! 	     since the top-level DW_AT_location assumes such.  See
! 	     the confusion in loc_descriptor for reference.  */
! 	  descr = loc_descriptor_from_tree (decl, 1);
! 	}
!       else
! 	{
! 	case REG:
! 	case SUBREG:
! 	case CONCAT:
! 	  descr = loc_descriptor (rtl, true);
! 	}
!       add_AT_location_description (die, attr, descr);
!       break;
! 
!     case PARALLEL:
!       {
! 	rtvec par_elems = XVEC (rtl, 0);
! 	int num_elem = GET_NUM_ELEM (par_elems);
! 	enum machine_mode mode;
! 	int i;
! 
! 	/* Create the first one, so we have something to add to.  */
! 	descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), true);
! 	mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
! 	add_loc_descr (&descr,
! 		       new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
! 	for (i = 1; i < num_elem; i++)
! 	  {
! 	    dw_loc_descr_ref temp;
! 
! 	    temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), true);
! 	    add_loc_descr (&descr, temp);
! 	    mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
! 	    add_loc_descr (&descr,
! 			   new_loc_descr (DW_OP_piece,
! 					  GET_MODE_SIZE (mode), 0));
! 	  }
!       }
!       add_AT_location_description (die, DW_AT_location, descr);
!       break;
! 
!     default:
!       abort ();
      }
  }
  
  /* If we don't have a copy of this variable in memory for some reason (such
--- 10089,10103 ----
      }
  
    rtl = rtl_for_decl_location (decl);
!   if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING))
      {
        add_const_value_attribute (die, rtl);
!       return;
      }
+ 
+   descr = loc_descriptor_from_tree (decl);
+   if (descr)
+     add_AT_location_description (die, attr, descr);
  }
  
  /* If we don't have a copy of this variable in memory for some reason (such
*************** add_bound_info (dw_die_ref subrange_die,
*** 10254,10260 ****
  	dw_die_ref ctx, decl_die;
  	dw_loc_descr_ref loc;
  
! 	loc = loc_descriptor_from_tree (bound, 0);
  	if (loc == NULL)
  	  break;
  
--- 10214,10220 ----
  	dw_die_ref ctx, decl_die;
  	dw_loc_descr_ref loc;
  
! 	loc = loc_descriptor_from_tree (bound);
  	if (loc == NULL)
  	  break;
  
*************** gen_subprogram_die (tree decl, dw_die_re
*** 11388,11394 ****
  
        if (cfun->static_chain_decl)
  	add_AT_location_description (subr_die, DW_AT_static_link,
! 		 loc_descriptor_from_tree (cfun->static_chain_decl, 0));
      }
  
    /* Now output descriptions of the arguments for this function. This gets
--- 11348,11354 ----
  
        if (cfun->static_chain_decl)
  	add_AT_location_description (subr_die, DW_AT_static_link,
! 		 loc_descriptor_from_tree (cfun->static_chain_decl));
      }
  
    /* Now output descriptions of the arguments for this function. This gets
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.701
diff -c -p -d -r1.701 expr.c
*** expr.c	10 Aug 2004 13:28:11 -0000	1.701
--- expr.c	11 Aug 2004 04:00:17 -0000
*************** expand_var (tree var)
*** 6008,6027 ****
        ? !TREE_ASM_WRITTEN (var)
        : !DECL_RTL_SET_P (var))
      {
!       if (TREE_CODE (var) == VAR_DECL && DECL_DEFER_OUTPUT (var))
! 	{
! 	  /* Prepare a mem & address for the decl.  */
! 	  rtx x;
! 
! 	  if (TREE_STATIC (var))
! 	    abort ();
! 
! 	  x = gen_rtx_MEM (DECL_MODE (var),
! 			   gen_reg_rtx (Pmode));
! 
! 	  set_mem_attributes (x, var, 1);
! 	  SET_DECL_RTL (var, x);
! 	}
        else if (lang_hooks.expand_decl (var))
  	/* OK.  */;
        else if (TREE_CODE (var) == VAR_DECL && !TREE_STATIC (var))
--- 6008,6015 ----
        ? !TREE_ASM_WRITTEN (var)
        : !DECL_RTL_SET_P (var))
      {
!       if (TREE_CODE (var) == VAR_DECL && DECL_VALUE_EXPR (var))
! 	/* Should be ignored.  */;
        else if (lang_hooks.expand_decl (var))
  	/* OK.  */;
        else if (TREE_CODE (var) == VAR_DECL && !TREE_STATIC (var))
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.60
diff -c -p -d -r2.60 gimplify.c
*** gimplify.c	7 Aug 2004 20:47:48 -0000	2.60
--- gimplify.c	11 Aug 2004 04:00:17 -0000
*************** gimplify_decl_expr (tree *stmt_p)
*** 976,995 ****
  	  /* This is a variable-sized decl.  Simplify its size and mark it
  	     for deferred expansion.  Note that mudflap depends on the format
  	     of the emitted code: see mx_register_decls().  */
! 	  tree t, args;
  
  	  gimplify_type_sizes (TREE_TYPE (decl), stmt_p);
  	  gimplify_one_sizepos (&DECL_SIZE (decl), stmt_p);
  	  gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p);
  
  	  args = tree_cons (NULL, DECL_SIZE_UNIT (decl), NULL);
! 	  t = build_fold_addr_expr (decl);
! 	  args = tree_cons (NULL, t, args);
! 	  t = implicit_built_in_decls[BUILT_IN_STACK_ALLOC];
  	  t = build_function_call_expr (t, args);
  
  	  gimplify_and_add (t, stmt_p);
! 	  DECL_DEFER_OUTPUT (decl) = 1;
  	}
  
        if (init && init != error_mark_node)
--- 976,1009 ----
  	  /* This is a variable-sized decl.  Simplify its size and mark it
  	     for deferred expansion.  Note that mudflap depends on the format
  	     of the emitted code: see mx_register_decls().  */
! 	  tree t, args, addr, ptr_type;
  
  	  gimplify_type_sizes (TREE_TYPE (decl), stmt_p);
  	  gimplify_one_sizepos (&DECL_SIZE (decl), stmt_p);
  	  gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p);
  
+ 	  /* All occurences of this decl in final gimplified code will be
+ 	     replaced by indirection.  Setting DECL_VALUE_EXPR does two
+ 	     things: First, it lets the rest of the gimplifier know what
+ 	     replacement to use.  Second, it lets the debug info know 
+ 	     where to find the value.  */
+ 	  ptr_type = build_pointer_type (TREE_TYPE (decl));
+ 	  addr = create_tmp_var (ptr_type, get_name (decl));
+ 	  DECL_IGNORED_P (addr) = 0;
+ 	  t = build_fold_indirect_ref (addr);
+ 	  DECL_VALUE_EXPR (decl) = t;
+ 
  	  args = tree_cons (NULL, DECL_SIZE_UNIT (decl), NULL);
! 	  t = built_in_decls[BUILT_IN_ALLOCA];
  	  t = build_function_call_expr (t, args);
+ 	  t = fold_convert (ptr_type, t);
+ 	  t = build2 (MODIFY_EXPR, void_type_node, addr, t);
  
  	  gimplify_and_add (t, stmt_p);
! 
! 	  /* Indicate that we need to restore the stack level when the
! 	     enclosing BIND_EXPR is exited.  */
! 	  gimplify_ctxp->save_stack = true;
  	}
  
        if (init && init != error_mark_node)
*************** gimplify_call_expr (tree *expr_p, tree *
*** 1834,1853 ****
    decl = get_callee_fndecl (*expr_p);
    if (decl && DECL_BUILT_IN (decl))
      {
!       tree new;
! 
!       /* 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;
! 
!       /* If it is restore of the stack, reset it, since it means we are
! 	 regimplifying the bind_expr.  Note that we use the fact that
! 	 for try_finally_expr, try part is processed first.  */
!       if (DECL_FUNCTION_CODE (decl) == BUILT_IN_STACK_RESTORE)
! 	gimplify_ctxp->save_stack = false;
! 
!       new = simplify_builtin (*expr_p, !want_value);
  
        if (new && new != *expr_p)
  	{
--- 1848,1854 ----
    decl = get_callee_fndecl (*expr_p);
    if (decl && DECL_BUILT_IN (decl))
      {
!       tree new = simplify_builtin (*expr_p, !want_value);
  
        if (new && new != *expr_p)
  	{
*************** gimplify_expr (tree *expr_p, tree *pre_p
*** 3781,3789 ****
  		abort ();
  #endif
  	      ret = GS_ERROR;
  	    }
! 	  else
! 	    ret = GS_ALL_DONE;
  	  break;
  
  	case SSA_NAME:
--- 3782,3800 ----
  		abort ();
  #endif
  	      ret = GS_ERROR;
+ 	      break;
  	    }
! 
! 	  /* If this is a local variable sized decl, it must be accessed
! 	     indirectly.  Perform that substitution.  */
! 	  if (DECL_VALUE_EXPR (tmp))
! 	    {
! 	      *expr_p = unshare_expr (DECL_VALUE_EXPR (tmp));
! 	      ret = GS_OK;
! 	      break;
! 	    }
! 
! 	  ret = GS_ALL_DONE;
  	  break;
  
  	case SSA_NAME:
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.384
diff -c -p -d -r1.384 stmt.c
*** stmt.c	9 Aug 2004 07:14:16 -0000	1.384
--- stmt.c	11 Aug 2004 04:00:17 -0000
*************** expand_decl (tree decl)
*** 2042,2081 ****
      }
  }
  
- /* Emit code to allocate T_SIZE bytes of dynamic stack space for ALLOC.  */
- void
- expand_stack_alloc (tree alloc, tree t_size)
- {
-   rtx address, dest, size;
-   tree var, type;
- 
-   if (TREE_CODE (alloc) != ADDR_EXPR)
-     abort ();
-   var = TREE_OPERAND (alloc, 0);
-   if (TREE_CODE (var) != VAR_DECL)
-     abort ();
- 
-   type = TREE_TYPE (var);
- 
-   /* Compute the variable's size, in bytes.  */
-   size = expand_expr (t_size, NULL_RTX, VOIDmode, 0);
-   free_temp_slots ();
- 
-   /* Allocate space on the stack for the variable.  */
-   address = XEXP (DECL_RTL (var), 0);
-   dest = allocate_dynamic_stack_space (size, address, TYPE_ALIGN (type));
-   if (dest != address)
-     emit_move_insn (address, dest);
- 
-   /* Indicate the alignment we actually gave this variable.  */
- #ifdef STACK_BOUNDARY
-   DECL_ALIGN (var) = STACK_BOUNDARY;
- #else
-   DECL_ALIGN (var) = BIGGEST_ALIGNMENT;
- #endif
-   DECL_USER_ALIGN (var) = 0;
- }
- 
  /* Emit code to save the current value of stack.  */
  rtx
  expand_stack_save (void)
--- 2042,2047 ----
Index: tree-mudflap.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-mudflap.c,v
retrieving revision 2.15
diff -c -p -d -r2.15 tree-mudflap.c
*** tree-mudflap.c	20 Jul 2004 20:01:12 -0000	2.15
--- tree-mudflap.c	11 Aug 2004 04:00:17 -0000
*************** mx_register_decls (tree decl, tree *stmt
*** 897,902 ****
--- 897,904 ----
            && TREE_ADDRESSABLE (decl)
            /* The type of the variable must be complete.  */
            && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
+ 	  /* The decl hasn't been decomposed somehow.  */
+ 	  && DECL_VALUE_EXPR (decl) == NULL
            /* Don't process the same decl twice.  */
            && ! mf_marked_p (decl))
          {
*************** mx_register_decls (tree decl, tree *stmt
*** 904,976 ****
            tree unregister_fncall, unregister_fncall_params;
            tree register_fncall, register_fncall_params;
  
!           if (DECL_DEFER_OUTPUT (decl))
!             {
!               /* Oh no ... it's probably a variable-length array (VLA).
!                  The size and address cannot be computed by merely
!                  looking at the DECL.  See gimplify_decl_stmt for the
!                  method by which VLA declarations turn into calls to
!                  BUILT_IN_STACK_ALLOC.  We assume that multiple
!                  VLAs declared later in the same block get allocation 
!                  code later than the others.  */
!               tree stack_alloc_call = NULL_TREE;
! 
!               while(! tsi_end_p (initially_stmts))
!                 {
!                   tree t = tsi_stmt (initially_stmts);
! 
!                   tree call = NULL_TREE;
!                   if (TREE_CODE (t) == CALL_EXPR)
!                     call = t;
!                   else if (TREE_CODE (t) == MODIFY_EXPR &&
!                            TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
!                     call = TREE_OPERAND (t, 1);
!                   else if (TREE_CODE (t) == TRY_FINALLY_EXPR)
!                     {
!                       /* We hope that this is the try/finally block sometimes
!                          constructed by gimplify_bind_expr() for a BIND_EXPR
!                          that contains VLAs.  This very naive recursion
!                          appears to be sufficient.  */
!                       initially_stmts = tsi_start (TREE_OPERAND (t, 0));
!                     }
! 
!                   if (call != NULL_TREE)
!                     {
!                       if (TREE_CODE (TREE_OPERAND(call, 0)) == ADDR_EXPR &&
!                           TREE_OPERAND (TREE_OPERAND (call, 0), 0) ==
!                                 implicit_built_in_decls [BUILT_IN_STACK_ALLOC])
!                         {
!                           tree stack_alloc_args = TREE_OPERAND (call, 1);
!                           tree stack_alloc_op1 = TREE_VALUE (stack_alloc_args);
!                           tree stack_alloc_op2 = TREE_VALUE (TREE_CHAIN (stack_alloc_args));
!                           
!                           if (TREE_CODE (stack_alloc_op1) == ADDR_EXPR &&
!                               TREE_OPERAND (stack_alloc_op1, 0) == decl)
!                             {
!                               /* Got it! */
!                               size = stack_alloc_op2;
!                               stack_alloc_call = call;
!                               /* Advance iterator to point past this allocation call.  */
!                               tsi_next (&initially_stmts);
!                               break;
!                             }
!                         }
!                     }
! 
!                   tsi_next (&initially_stmts);
!                 }
! 
!               if (stack_alloc_call == NULL_TREE)
!                 {
!                   warning ("mudflap cannot handle variable-sized declaration `%s'",
!                          IDENTIFIER_POINTER (DECL_NAME (decl)));
!                   break;
!                 }
!             }
!           else
!             {
!               size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
!             }
  
            /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
            unregister_fncall_params =
--- 906,912 ----
            tree unregister_fncall, unregister_fncall_params;
            tree register_fncall, register_fncall_params;
  
! 	  size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
  
            /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
            unregister_fncall_params =
Index: tree-nested.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-nested.c,v
retrieving revision 2.10
diff -c -p -d -r2.10 tree-nested.c
*** tree-nested.c	22 Jul 2004 08:20:38 -0000	2.10
--- tree-nested.c	11 Aug 2004 04:00:17 -0000
*************** convert_local_reference (tree *tp, int *
*** 855,861 ****
  {
    struct walk_stmt_info *wi = data;
    struct nesting_info *info = wi->info;
!   tree t = *tp, field, x, y;
  
    switch (TREE_CODE (t))
      {
--- 855,861 ----
  {
    struct walk_stmt_info *wi = data;
    struct nesting_info *info = wi->info;
!   tree t = *tp, field, x;
  
    switch (TREE_CODE (t))
      {
*************** convert_local_reference (tree *tp, int *
*** 909,948 ****
        }
        break;
  
-     case CALL_EXPR:
-       *walk_subtrees = 1;
- 
-       /* Ready for some fun?  We need to recognize
- 	    __builtin_stack_alloc (&x, n)
- 	 and insert
- 	    FRAME.x = &x
- 	 after that.  X should have use_pointer_in_frame set.  We can't
- 	 do this any earlier, since we can't meaningfully evaluate &x.  */
- 
-       x = get_callee_fndecl (t);
-       if (!x || DECL_BUILT_IN_CLASS (x) != BUILT_IN_NORMAL)
- 	break;
-       if (DECL_FUNCTION_CODE (x) != BUILT_IN_STACK_ALLOC)
- 	break;
-       t = TREE_VALUE (TREE_OPERAND (t, 1));
-       if (TREE_CODE (t) != ADDR_EXPR)
- 	abort ();
-       t = TREE_OPERAND (t, 0);
-       if (TREE_CODE (t) != VAR_DECL)
- 	abort ();
-       field = lookup_field_for_decl (info, t, NO_INSERT);
-       if (!field)
- 	break;
-       if (!use_pointer_in_frame (t))
- 	abort ();
- 
-       x = build_addr (t);
-       y = get_frame_field (info, info->context, field, &wi->tsi);
-       x = build (MODIFY_EXPR, void_type_node, y, x);
-       SET_EXPR_LOCUS (x, EXPR_LOCUS (tsi_stmt (wi->tsi)));
-       tsi_link_after (&wi->tsi, x, TSI_SAME_STMT);
-       break;
- 
      case REALPART_EXPR:
      case IMAGPART_EXPR:
      case COMPONENT_REF:
--- 909,914 ----
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.585
diff -c -p -d -r1.585 tree.h
*** tree.h	9 Aug 2004 19:13:07 -0000	1.585
--- tree.h	11 Aug 2004 04:00:18 -0000
*************** struct tree_binfo GTY (())
*** 2027,2032 ****
--- 2027,2039 ----
     entire function.  */
  #define DECL_SAVED_TREE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.saved_tree)
  
+ /* In a VAR_DECL or PARM_DECL, the location at which the value may be found,
+    if transformations have made this more complicated than evaluating the
+    decl itself.  This should only be used for debugging; once this field has
+    been set, the decl itself may not legitimately appear in the function.  */
+ #define DECL_VALUE_EXPR(NODE) \
+   (TREE_CHECK2 (NODE, VAR_DECL, PARM_DECL)->decl.saved_tree)
+ 
  /* List of FUNCTION_DECLs inlined into this function's body.  */
  #define DECL_INLINED_FNS(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.inlined_fns)
  
*************** struct tree_decl GTY(())
*** 2278,2284 ****
      int GTY ((tag ("VAR_DECL"))) i;
    } GTY ((desc ("TREE_CODE((tree) &(%0))"))) u2;
  
!   /* In a FUNCTION_DECL, this is DECL_SAVED_TREE.  */
    tree saved_tree;
  
    /* In a FUNCTION_DECL, these are function data which is to be kept
--- 2285,2292 ----
      int GTY ((tag ("VAR_DECL"))) i;
    } GTY ((desc ("TREE_CODE((tree) &(%0))"))) u2;
  
!   /* In a FUNCTION_DECL, this is DECL_SAVED_TREE.
!      In a VAR_DECL or PARM_DECL, this is DECL_VALUE_EXPR.  */
    tree saved_tree;
  
    /* In a FUNCTION_DECL, these are function data which is to be kept
*************** extern void expand_label (tree);
*** 3353,3359 ****
  extern void expand_goto (tree);
  extern void expand_asm (tree, int);
  
- extern void expand_stack_alloc (tree, tree);
  extern rtx expand_stack_save (void);
  extern void expand_stack_restore (tree);
  extern void expand_return (tree);
--- 3361,3366 ----
Index: ada/utils.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ada/utils.c,v
retrieving revision 1.74
diff -c -p -d -r1.74 utils.c
*** ada/utils.c	9 Aug 2004 12:24:22 -0000	1.74
--- ada/utils.c	11 Aug 2004 04:00:18 -0000
*************** gnat_install_builtins ()
*** 481,486 ****
--- 481,489 ----
    gnat_define_builtin ("__builtin_clzll", ftype, BUILT_IN_CLZLL, "clzll",
  		       true);
  
+   /* The init_trampoline and adjust_trampoline builtins aren't used directly.
+      They are inserted during lowering of nested functions.  */
+ 
    tmp = tree_cons (NULL_TREE, ptr_void_type_node, void_list_node);
    tmp = tree_cons (NULL_TREE, ptr_void_type_node, tmp);
    tmp = tree_cons (NULL_TREE, ptr_void_type_node, tmp);
*************** gnat_install_builtins ()
*** 493,513 ****
    gnat_define_builtin ("__builtin_adjust_trampoline", ftype,
  		       BUILT_IN_ADJUST_TRAMPOLINE, "adjust_trampoline", true);
  
!   tmp = tree_cons (NULL_TREE, ptr_void_type_node, void_list_node);
!   tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
!   ftype = build_function_type (ptr_void_type_node, tmp);
!   gnat_define_builtin ("__builtin_stack_alloc", ftype, BUILT_IN_STACK_ALLOC,
! 		       "stack_alloc", false);
  
-   /* The stack_save and stack_restore builtins aren't used directly.  They
-      are inserted during gimplification to implement stack_alloc calls.  */
    ftype = build_function_type (ptr_void_type_node, void_list_node);
    gnat_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE,
  		       "stack_save", false);
    tmp = tree_cons (NULL_TREE, ptr_void_type_node, void_list_node);
    ftype = build_function_type (void_type_node, tmp);
    gnat_define_builtin ("__builtin_stack_restore", ftype,
  		       BUILT_IN_STACK_RESTORE, "stack_restore", false);
  }
  
  /* Create the predefined scalar types such as `integer_type_node' needed
--- 496,519 ----
    gnat_define_builtin ("__builtin_adjust_trampoline", ftype,
  		       BUILT_IN_ADJUST_TRAMPOLINE, "adjust_trampoline", true);
  
!   /* The stack_save, stack_restore, and alloca builtins aren't used directly.
!      They are inserted during gimplification to implement variable sized stack
!      allocation.  */
  
    ftype = build_function_type (ptr_void_type_node, void_list_node);
    gnat_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE,
  		       "stack_save", false);
+ 
    tmp = tree_cons (NULL_TREE, ptr_void_type_node, void_list_node);
    ftype = build_function_type (void_type_node, tmp);
    gnat_define_builtin ("__builtin_stack_restore", ftype,
  		       BUILT_IN_STACK_RESTORE, "stack_restore", false);
+ 
+   tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
+   ftype = build_function_type (ptr_void_type_node, tmp);
+   gnat_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA,
+ 		       "alloca", false);
+ 
  }
  
  /* Create the predefined scalar types such as `integer_type_node' needed
Index: fortran/f95-lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/f95-lang.c,v
retrieving revision 1.10
diff -c -p -d -r1.10 f95-lang.c
*** fortran/f95-lang.c	6 Aug 2004 20:45:14 -0000	1.10
--- fortran/f95-lang.c	11 Aug 2004 04:00:18 -0000
*************** gfc_init_builtin_functions (void)
*** 794,814 ****
    gfc_define_builtin ("__builtin_adjust_trampoline", ftype,
  		      BUILT_IN_ADJUST_TRAMPOLINE, "adjust_trampoline", true);
  
!   tmp = tree_cons (NULL_TREE, pvoid_type_node, void_list_node);
!   tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
!   ftype = build_function_type (pvoid_type_node, tmp);
!   gfc_define_builtin ("__builtin_stack_alloc", ftype, BUILT_IN_STACK_ALLOC,
! 		      "stack_alloc", false);
  
-   /* The stack_save and stack_restore builtins aren't used directly.  They
-      are inserted during gimplification to implement stack_alloc calls.  */
    ftype = build_function_type (pvoid_type_node, void_list_node);
    gfc_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE,
  		      "stack_save", false);
    tmp = tree_cons (NULL_TREE, pvoid_type_node, void_list_node);
    ftype = build_function_type (void_type_node, tmp);
    gfc_define_builtin ("__builtin_stack_restore", ftype, BUILT_IN_STACK_RESTORE,
  		      "stack_restore", false);
  }
  
  #undef DEFINE_MATH_BUILTIN
--- 794,816 ----
    gfc_define_builtin ("__builtin_adjust_trampoline", ftype,
  		      BUILT_IN_ADJUST_TRAMPOLINE, "adjust_trampoline", true);
  
!   /* The stack_save, stack_restore, and alloca builtins aren't used directly.
!      They are inserted during gimplification to implement variable sized
!      stack allocation.  */
  
    ftype = build_function_type (pvoid_type_node, void_list_node);
    gfc_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE,
  		      "stack_save", false);
+ 
    tmp = tree_cons (NULL_TREE, pvoid_type_node, void_list_node);
    ftype = build_function_type (void_type_node, tmp);
    gfc_define_builtin ("__builtin_stack_restore", ftype, BUILT_IN_STACK_RESTORE,
  		      "stack_restore", false);
+ 
+   tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
+   ftype = build_function_type (pvoid_type_node, tmp);
+   gfc_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA,
+ 		      "alloca", false);
  }
  
  #undef DEFINE_MATH_BUILTIN
Index: fortran/trans-array.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/trans-array.c,v
retrieving revision 1.13
diff -c -p -d -r1.13 trans-array.c
*** fortran/trans-array.c	9 Aug 2004 23:32:53 -0000	1.13
--- fortran/trans-array.c	11 Aug 2004 04:00:18 -0000
*************** gfc_trans_auto_array_allocation (tree de
*** 2926,2940 ****
      {
        gfc_trans_init_string_length (sym->ts.cl, &block);
  
!       DECL_DEFER_OUTPUT (decl) = 1;
! 
!       /* Generate code to allocate the automatic variable.  It will be
! 	 freed automatically.  */
!       tmp = gfc_build_addr_expr (NULL, decl);
!       args = gfc_chainon_list (NULL_TREE, tmp);
!       args = gfc_chainon_list (args, sym->ts.cl->backend_decl);
!       tmp = gfc_build_function_call (built_in_decls[BUILT_IN_STACK_ALLOC],
! 				     args);
        gfc_add_expr_to_block (&block, tmp);
      }
  
--- 2926,2934 ----
      {
        gfc_trans_init_string_length (sym->ts.cl, &block);
  
!       /* Emit a DECL_EXPR for this variable, which will cause the
! 	 gimplifier to allocate stoage, and all that good stuff.  */
!       tmp = build (DECL_EXPR, TREE_TYPE (decl), decl);
        gfc_add_expr_to_block (&block, tmp);
      }
  
Index: fortran/trans-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/trans-decl.c,v
retrieving revision 1.26
diff -c -p -d -r1.26 trans-decl.c
*** fortran/trans-decl.c	5 Aug 2004 05:51:59 -0000	1.26
--- fortran/trans-decl.c	11 Aug 2004 04:00:18 -0000
*************** gfc_trans_auto_character_variable (gfc_s
*** 1626,1632 ****
  {
    stmtblock_t body;
    tree decl;
-   tree args;
    tree tmp;
  
    assert (sym->backend_decl);
--- 1626,1631 ----
*************** gfc_trans_auto_character_variable (gfc_s
*** 1639,1661 ****
  
    decl = sym->backend_decl;
  
!   DECL_DEFER_OUTPUT (decl) = 1;
! 
!   /* Since we don't use a DECL_STMT or equivalent, we have to deal
!      with getting these gimplified.  But we can't gimplify it yet since
!      we're still generating statements.
! 
!      ??? This should be cleaned up and handled like other front ends.  */
!   gfc_add_expr_to_block (&body, save_expr (DECL_SIZE (decl)));
!   gfc_add_expr_to_block (&body, save_expr (DECL_SIZE_UNIT (decl)));
! 
!   /* Generate code to allocate the automatic variable.  It will be freed
!      automatically.  */
!   tmp = gfc_build_addr_expr (NULL, decl);
!   args = gfc_chainon_list (NULL_TREE, tmp);
!   args = gfc_chainon_list (args, sym->ts.cl->backend_decl);
!   tmp = gfc_build_function_call (built_in_decls[BUILT_IN_STACK_ALLOC], args);
    gfc_add_expr_to_block (&body, tmp);
    gfc_add_expr_to_block (&body, fnbody);
    return gfc_finish_block (&body);
  }
--- 1638,1648 ----
  
    decl = sym->backend_decl;
  
!   /* Emit a DECL_EXPR for this variable, which will cause the
!      gimplifier to allocate stoage, and all that good stuff.  */
!   tmp = build (DECL_EXPR, TREE_TYPE (decl), decl);
    gfc_add_expr_to_block (&body, tmp);
+ 
    gfc_add_expr_to_block (&body, fnbody);
    return gfc_finish_block (&body);
  }


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