OSDN Git Service

* tree.h (TREE_ADDRESSABLE): Document its effect for function types.
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 8 Apr 2010 20:16:36 +0000 (20:16 +0000)
committerMasaki Muranaka <monaka@monami-software.com>
Sun, 23 May 2010 05:17:56 +0000 (14:17 +0900)
* calls.c (expand_call): Pass the function type to aggregate_value_p.
* function.c (aggregate_value_p): Do not honor DECL_BY_REFERENCE on
the target function of a CALL_EXPR.  Honor TREE_ADDRESSABLE on the
function type instead.  Reorder and simplify checks.

* gimplify.c (gimplify_modify_expr_rhs) <WITH_SIZE_EXPR>: New case.
ada/
* gcc-interface/ada-tree.h (TYPE_RETURNS_UNCONSTRAINED_P): Rename into.
(TYPE_RETURN_UNCONSTRAINED_P): ...this.
(TYPE_RETURNS_BY_REF_P): Rename into.
(TYPE_RETURN_BY_DIRECT_REF_P): ...this.
(TYPE_RETURNS_BY_TARGET_PTR_P): Delete.
* gcc-interface/gigi.h (create_subprog_type): Adjust parameter names.
(build_return_expr): Likewise.
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Subprogram_Type>:
Rename local variables.  If the return Mechanism is By_Reference, pass
return_by_invisible_ref_p to create_subprog_type instead of toggling
TREE_ADDRESSABLE.  Test return_by_invisible_ref_p in order to annotate
the mechanism.  Use regular return for contrained types with non-static
size and return by invisible reference for unconstrained return types
with default discriminants.  Update comment.
* gcc-interface/trans.c (Subprogram_Body_to_gnu): If the function
returns by invisible reference, turn the RESULT_DECL into a pointer.
Do not handle DECL_BY_REF_P in the CICO case here.
(call_to_gnu): Remove code handling return by target pointer.  For a
function call, if the return type has non-constant size, generate the
assignment with an INIT_EXPR.
(gnat_to_gnu) <N_Return_Statement>: Remove dead code in the CICO case.
If the function returns by invisible reference, build the copy return
operation manually.
(add_decl_expr): Initialize the variable with an INIT_EXPR.
* gcc-interface/utils.c (create_subprog_type): Adjust parameter names.
Adjust for renaming of macros.  Copy the node only when necessary.
(create_subprog_decl): Do not toggle TREE_ADDRESSABLE on the return
type, only change DECL_BY_REFERENCE on the RETURN_DECL.
(convert_from_reference): Delete.
(is_byref_result): Likewise.
(gnat_genericize_r): Likewise.
(gnat_genericize): Likewise.
(end_subprog_body): Do not call gnat_genericize.
* gcc-interface/utils2.c (build_binary_op) <INIT_EXPR>: New case.
(build_return_expr): Adjust parameter names, logic and comment.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158139 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/gcc-interface/trans.c
gcc/gimplify.c

index f676ed4..565f832 100644 (file)
@@ -1,3 +1,13 @@
+2010-04-08  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * tree.h (TREE_ADDRESSABLE): Document its effect for function types.
+       * calls.c (expand_call): Pass the function type to aggregate_value_p.
+       * function.c (aggregate_value_p): Do not honor DECL_BY_REFERENCE on
+       the target function of a CALL_EXPR.  Honor TREE_ADDRESSABLE on the
+       function type instead.  Reorder and simplify checks.
+
+       * gimplify.c (gimplify_modify_expr_rhs) <WITH_SIZE_EXPR>: New case.
+
 2010-04-08  Jing Yu  <jingyu@google.com>
            Zdenek Dvorak  <ook@ucw.cz>
 
index c740fa8..e43a534 100644 (file)
@@ -1,3 +1,41 @@
+2010-04-08  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc-interface/ada-tree.h (TYPE_RETURNS_UNCONSTRAINED_P): Rename into.
+       (TYPE_RETURN_UNCONSTRAINED_P): ...this.
+       (TYPE_RETURNS_BY_REF_P): Rename into.
+       (TYPE_RETURN_BY_DIRECT_REF_P): ...this.
+       (TYPE_RETURNS_BY_TARGET_PTR_P): Delete.
+       * gcc-interface/gigi.h (create_subprog_type): Adjust parameter names.
+       (build_return_expr): Likewise.
+       * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Subprogram_Type>:
+       Rename local variables.  If the return Mechanism is By_Reference, pass
+       return_by_invisible_ref_p to create_subprog_type instead of toggling
+       TREE_ADDRESSABLE.  Test return_by_invisible_ref_p in order to annotate
+       the mechanism.  Use regular return for contrained types with non-static
+       size and return by invisible reference for unconstrained return types
+       with default discriminants.  Update comment.
+       * gcc-interface/trans.c (Subprogram_Body_to_gnu): If the function
+       returns by invisible reference, turn the RESULT_DECL into a pointer.
+       Do not handle DECL_BY_REF_P in the CICO case here.
+       (call_to_gnu): Remove code handling return by target pointer.  For a
+       function call, if the return type has non-constant size, generate the
+       assignment with an INIT_EXPR.
+       (gnat_to_gnu) <N_Return_Statement>: Remove dead code in the CICO case.
+       If the function returns by invisible reference, build the copy return
+       operation manually.
+       (add_decl_expr): Initialize the variable with an INIT_EXPR.
+       * gcc-interface/utils.c (create_subprog_type): Adjust parameter names.
+       Adjust for renaming of macros.  Copy the node only when necessary.
+       (create_subprog_decl): Do not toggle TREE_ADDRESSABLE on the return
+       type, only change DECL_BY_REFERENCE on the RETURN_DECL.
+       (convert_from_reference): Delete.
+       (is_byref_result): Likewise.
+       (gnat_genericize_r): Likewise.
+       (gnat_genericize): Likewise.
+       (end_subprog_body): Do not call gnat_genericize.
+       * gcc-interface/utils2.c (build_binary_op) <INIT_EXPR>: New case.
+       (build_return_expr): Adjust parameter names, logic and comment.
+
 2010-04-07  Eric Botcazou  <ebotcazou@adacore.com>
 
        * exp_pakd.adb (Create_Packed_Array_Type): Always use a modular type
index 0f4cef0..640dab1 100644 (file)
@@ -2619,8 +2619,9 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
      subprogram.  */
   tree gnu_subprog = gnat_to_gnu (Name (gnat_node));
   /* The FUNCTION_TYPE node giving the GCC type of the subprogram.  */
-  tree gnu_subprog_type = TREE_TYPE (gnu_subprog);
-  tree gnu_subprog_addr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_subprog);
+  tree gnu_subprog_type = TREE_TYPE (gnu_subprog_node);
+  tree gnu_subprog_addr
+    = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_subprog_node);
   Entity_Id gnat_formal;
   Node_Id gnat_actual;
   VEC(tree,gc) *gnu_actual_vec = NULL;
@@ -2644,33 +2645,19 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
           gnat_actual = Next_Actual (gnat_actual))
        add_stmt (gnat_to_gnu (gnat_actual));
 
-      if (Nkind (gnat_node) == N_Function_Call && !gnu_target)
-       {
-         tree gnu_obj_type;
-
-         if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_ret_type)))
-           gnu_obj_type
-             = maybe_pad_type (gnu_ret_type,
-                               max_size (TYPE_SIZE (gnu_ret_type), true),
-                               0, Etype (Name (gnat_node)), false, false,
-                               false, true);
-         else
-           gnu_obj_type = gnu_ret_type;
-
-         /* ??? We may be about to create a static temporary if we happen to
-            be at the global binding level.  That's a regression from what
-            the 3.x back-end would generate in the same situation, but we
-            don't have a mechanism in Gigi for creating automatic variables
-            in the elaboration routines.  */
-         gnu_target
-           = create_var_decl (create_tmp_var_name ("LR"), NULL, gnu_obj_type,
-                              NULL, false, false, false, false, NULL,
-                              gnat_node);
-
-         *gnu_result_type_p = gnu_ret_type;
-       }
+      {
+       tree call_expr
+         = build_call_raise (PE_Stubbed_Subprogram_Called, gnat_node,
+                             N_Raise_Program_Error);
 
-      return call_expr;
+       if (Nkind (gnat_node) == N_Function_Call && !gnu_target)
+         {
+           *gnu_result_type_p = TREE_TYPE (gnu_subprog_type);
+           return build1 (NULL_EXPR, *gnu_result_type_p, call_expr);
+         }
+       else
+         return call_expr;
+      }
     }
 
   /* The only way we can be making a call via an access type is if Name is an
@@ -3001,33 +2988,13 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
                                      nreverse (gnu_actual_list));
   set_expr_location_from_node (gnu_subprog_call, gnat_node);
 
-  /* If we return by passing a target, the result is the target after the
-     call.  We must not emit the call directly here because this might be
-     evaluated as part of an expression with conditions to control whether
-     the call should be emitted or not.  */
-  if (TYPE_RETURNS_BY_TARGET_PTR_P (gnu_subprog_type))
+  /* If it's a function call, the result is the call expression unless a target
+     is specified, in which case we copy the result into the target and return
+     the assignment statement.  */
+  if (Nkind (gnat_node) == N_Function_Call)
     {
-      /* Conceptually, what we need is a COMPOUND_EXPR of the call followed by
-        the target object.  Doing so would potentially be inefficient though,
-        as this expression might be wrapped up into a SAVE_EXPR later, which
-        would incur a pointless temporary copy of the whole object.
-
-        What we do instead is build a COMPOUND_EXPR returning the address of
-        the target, and then dereference.  Wrapping up the COMPOUND_EXPR into
-        a SAVE_EXPR then only incurs a mere pointer copy.  */
-      tree gnu_target_addr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_target);
-      set_expr_location_from_node (gnu_target_addr, gnat_node);
-      gnu_result = build2 (COMPOUND_EXPR, TREE_TYPE (gnu_target_addr),
-                          gnu_subprog_call, gnu_target_addr);
-      return build_unary_op (INDIRECT_REF, NULL_TREE, gnu_result);
-    }
-
-  /* If it is a function call, the result is the call expression unless
-     a target is specified, in which case we copy the result into the target
-     and return the assignment statement.  */
-  else if (Nkind (gnat_node) == N_Function_Call)
-    {
-      tree gnu_result = gnu_call;
+      gnu_result = gnu_subprog_call;
+      enum tree_code op_code;
 
       /* If the function returns an unconstrained array or by direct reference,
         we have to dereference the pointer.  */
@@ -3037,15 +3004,6 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
 
       if (gnu_target)
        {
-         Node_Id gnat_parent = Parent (gnat_node);
-         enum tree_code op_code;
-
-         /* If range check is needed, emit code to generate it.  */
-         if (Do_Range_Check (gnat_node))
-           gnu_result
-             = emit_range_check (gnu_result, Etype (Name (gnat_parent)),
-                                 gnat_parent);
-
          /* ??? If the return type has non-constant size, then force the
             return slot optimization as we would not be able to generate
             a temporary.  That's what has been done historically.  */
@@ -3056,9 +3014,6 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
 
          gnu_result
            = build_binary_op (op_code, NULL_TREE, gnu_target, gnu_result);
-         add_stmt_with_node (gnu_result, gnat_parent);
-         gnat_poplevel ();
-         gnu_result = end_stmt_group ();
        }
       else
        {
index 2b40272..890ab23 100644 (file)
@@ -4308,8 +4308,66 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
              }
          }
 
-       default:
-         break;
+       ret = GS_UNHANDLED;
+       break;
+
+      case WITH_SIZE_EXPR:
+       /* Likewise for calls that return an aggregate of non-constant size,
+          since we would not be able to generate a temporary at all.  */
+       if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR)
+         {
+           *from_p = TREE_OPERAND (*from_p, 0);
+           ret = GS_OK;
+         }
+       else
+         ret = GS_UNHANDLED;
+       break;
+
+       /* If we're initializing from a container, push the initialization
+          inside it.  */
+      case CLEANUP_POINT_EXPR:
+      case BIND_EXPR:
+      case STATEMENT_LIST:
+       {
+         tree wrap = *from_p;
+         tree t;
+
+         ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
+                              fb_lvalue);
+         if (ret != GS_ERROR)
+           ret = GS_OK;
+
+         t = voidify_wrapper_expr (wrap, *expr_p);
+         gcc_assert (t == *expr_p);
+
+         if (want_value)
+           {
+             gimplify_and_add (wrap, pre_p);
+             *expr_p = unshare_expr (*to_p);
+           }
+         else
+           *expr_p = wrap;
+         return GS_OK;
+       }
+
+      case COMPOUND_LITERAL_EXPR:
+       {
+         tree complit = TREE_OPERAND (*expr_p, 1);
+         tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
+         tree decl = DECL_EXPR_DECL (decl_s);
+         tree init = DECL_INITIAL (decl);
+
+         /* struct T x = (struct T) { 0, 1, 2 } can be optimized
+            into struct T x = { 0, 1, 2 } if the address of the
+            compound literal has never been taken.  */
+         if (!TREE_ADDRESSABLE (complit)
+             && !TREE_ADDRESSABLE (decl)
+             && init)
+           {
+             *expr_p = copy_node (*expr_p);
+             TREE_OPERAND (*expr_p, 1) = init;
+             return GS_OK;
+           }
        }
     }
   while (changed);