OSDN Git Service

PR c/12802
[pf3gnuchains/gcc-fork.git] / gcc / tree-nested.c
index 668861c..d2608a8 100644 (file)
@@ -55,7 +55,7 @@
 
    The implementation here is much more direct.  Everything that can be
    referenced by an inner function is a member of an explicitly created
-   structure herein called the "nonlocal frame struct".  The incomming
+   structure herein called the "nonlocal frame struct".  The incoming
    static chain for a nested function is a pointer to this struct in 
    the parent.  In this way, we settle on known offsets from a known
    base, and so are decoupled from the logic that places objects in the
@@ -132,19 +132,17 @@ create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
 {
   tree tmp_var;
 
-#if defined ENABLE_CHECKING
   /* If the type is of variable size or a type which must be created by the
      frontend, something is wrong.  Note that we explicitly allow
      incomplete types here, since we create them ourselves here.  */
-  if (TREE_ADDRESSABLE (type)
-      || (TYPE_SIZE_UNIT (type)
-         && TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST))
-    abort ();
-#endif
+  gcc_assert (!TREE_ADDRESSABLE (type));
+  gcc_assert (!TYPE_SIZE_UNIT (type)
+             || TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST);
 
   tmp_var = create_tmp_var_raw (type, prefix);
   DECL_CONTEXT (tmp_var) = info->context;
   TREE_CHAIN (tmp_var) = info->new_local_var_chain;
+  DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1;
   info->new_local_var_chain = tmp_var;
 
   return tmp_var;
@@ -152,7 +150,7 @@ create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
 
 /* Take the address of EXP.  Mark it for addressability as necessary.  */
 
-static tree
+tree
 build_addr (tree exp)
 {
   tree base = exp;
@@ -248,8 +246,7 @@ lookup_field_for_decl (struct nesting_info *info, tree decl,
   slot = htab_find_slot (info->var_map, &dummy, insert);
   if (!slot)
     {
-      if (insert == INSERT)
-       abort ();
+      gcc_assert (insert != INSERT);
       return NULL;
     }
   elt = *slot;
@@ -372,7 +369,7 @@ init_tmp_var (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi)
 /* Similarly, but only do so to force EXP to satisfy is_gimple_val.  */
 
 static tree
-gimplify_val (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi)
+tsi_gimplify_val (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi)
 {
   if (is_gimple_val (exp))
     return exp;
@@ -404,7 +401,7 @@ get_trampoline_type (void)
       align = STACK_BOUNDARY;
     }
 
-  t = build_index_type (build_int_2 (size - 1, 0));
+  t = build_index_type (build_int_cst (NULL_TREE, size - 1));
   t = build_array_type (char_type_node, t);
   t = build_decl (FIELD_DECL, get_identifier ("__data"), t);
   DECL_ALIGN (t) = align;
@@ -433,8 +430,7 @@ lookup_tramp_for_decl (struct nesting_info *info, tree decl,
   slot = htab_find_slot (info->var_map, &dummy, insert);
   if (!slot)
     {
-      if (insert == INSERT)
-       abort ();
+      gcc_assert (insert != INSERT);
       return NULL;
     }
   elt = *slot;
@@ -487,7 +483,8 @@ get_nl_goto_field (struct nesting_info *info)
       size = size / GET_MODE_SIZE (Pmode);
       size = size + 1;
 
-      type = build_array_type (type, build_index_type (build_int_2 (size, 0)));
+      type = build_array_type
+       (type, build_index_type (build_int_cst (NULL_TREE, size)));
 
       field = make_node (FIELD_DECL);
       DECL_NAME (field) = get_identifier ("__nl_goto_buf");
@@ -789,7 +786,7 @@ convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
               where we only accept variables (and min_invariant, presumably),
               then compute the address into a temporary.  */
            if (save_val_only)
-             *tp = gimplify_val (wi->info, t, &wi->tsi);
+             *tp = tsi_gimplify_val (wi->info, t, &wi->tsi);
          }
       }
       break;
@@ -834,7 +831,7 @@ convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
       break;
 
     default:
-      if (!DECL_P (t) && !TYPE_P (t))
+      if (!IS_TYPE_OR_DECL_P (t))
        {
          *walk_subtrees = 1;
           wi->val_only = true;
@@ -854,7 +851,7 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
 {
   struct walk_stmt_info *wi = data;
   struct nesting_info *info = wi->info;
-  tree t = *tp, field, x, y;
+  tree t = *tp, field, x;
 
   switch (TREE_CODE (t))
     {
@@ -903,45 +900,11 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
            /* If we are in a context where we only accept values, then
               compute the address into a temporary.  */
            if (save_val_only)
-             *tp = gimplify_val (wi->info, t, &wi->tsi);
+             *tp = tsi_gimplify_val (wi->info, t, &wi->tsi);
          }
       }
       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:
@@ -982,7 +945,7 @@ convert_local_reference (tree *tp, int *walk_subtrees, void *data)
       break;
 
     default:
-      if (!DECL_P (t) && !TYPE_P (t))
+      if (!IS_TYPE_OR_DECL_P (t))
        {
          *walk_subtrees = 1;
          wi->val_only = true;
@@ -1040,7 +1003,7 @@ convert_nl_goto_reference (tree *tp, int *walk_subtrees, void *data)
   field = get_nl_goto_field (i);
   x = get_frame_field (info, target_context, field, &wi->tsi);
   x = build_addr (x);
-  x = gimplify_val (info, x, &wi->tsi);
+  x = tsi_gimplify_val (info, x, &wi->tsi);
   arg = tree_cons (NULL, x, NULL);
   x = build_addr (new_label);
   arg = tree_cons (NULL, x, arg);
@@ -1138,7 +1101,7 @@ convert_tramp_reference (tree *tp, int *walk_subtrees, void *data)
       /* Compute the address of the field holding the trampoline.  */
       x = get_frame_field (info, target_context, x, &wi->tsi);
       x = build_addr (x);
-      x = gimplify_val (info, x, &wi->tsi);
+      x = tsi_gimplify_val (info, x, &wi->tsi);
       arg = tree_cons (NULL, x, NULL);
 
       /* Do machine-specific ugliness.  Normally this will involve
@@ -1161,7 +1124,7 @@ convert_tramp_reference (tree *tp, int *walk_subtrees, void *data)
       break;
 
     default:
-      if (!DECL_P (t) && !TYPE_P (t))
+      if (!IS_TYPE_OR_DECL_P (t))
        *walk_subtrees = 1;
       break;
     }
@@ -1195,7 +1158,8 @@ convert_call_expr (tree *tp, int *walk_subtrees, void *data)
 
     case RETURN_EXPR:
     case MODIFY_EXPR:
-      /* Only return and modify may contain calls.  */
+    case WITH_SIZE_EXPR:
+      /* Only return modify and with_size_expr may contain calls.  */
       *walk_subtrees = 1;
       break;
 
@@ -1225,12 +1189,7 @@ convert_all_function_calls (struct nesting_info *root)
       if (root->outer && !root->chain_decl && !root->chain_field)
        DECL_NO_STATIC_CHAIN (root->context) = 1;
       else
-       {
-#ifdef ENABLE_CHECKING
-         if (DECL_NO_STATIC_CHAIN (root->context))
-           abort ();
-#endif
-       }
+       gcc_assert (!DECL_NO_STATIC_CHAIN (root->context));
 
       root = root->next;
     }
@@ -1248,6 +1207,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
   tree stmt_list = NULL;
   tree context = root->context;
   struct function *sf;
+  struct cgraph_node *node;
 
   /* If we created a non-local frame type or decl, we need to lay them
      out at this time.  */
@@ -1358,6 +1318,15 @@ finalize_nesting_tree_1 (struct nesting_info *root)
 
   /* Dump the translated tree function.  */
   dump_function (TDI_nested, root->context);
+  node = cgraph_node (root->context);
+
+  /* For nested functions update the cgraph to reflect unnesting.
+     We also delay finalizing of these functions up to this point.  */
+  if (node->origin)
+    {
+       cgraph_unnest_node (cgraph_node (root->context));
+       cgraph_finalize_function (root->context, true);
+    }
 }
 
 static void