OSDN Git Service

* function.c (aggregate_value_p): Honor DECL_BY_REFERENCE on
[pf3gnuchains/gcc-fork.git] / gcc / function.c
index 26c99fa..177b618 100644 (file)
@@ -332,8 +332,6 @@ free_after_compilation (struct function *f)
   f->x_stack_check_probe_note = NULL;
   f->x_arg_pointer_save_area = NULL;
   f->x_parm_birth_insn = NULL;
-  f->original_arg_vector = NULL;
-  f->original_decl_initial = NULL;
   f->epilogue_delay_list = NULL;
 }
 \f
@@ -546,14 +544,18 @@ insert_slot_to_list (struct temp_slot *temp, struct temp_slot **list)
 static struct temp_slot **
 temp_slots_at_level (int level)
 {
+  if (level >= (int) VEC_length (temp_slot_p, used_temp_slots))
+    {
+      size_t old_length = VEC_length (temp_slot_p, used_temp_slots);
+      temp_slot_p *p;
 
-  if (!used_temp_slots)
-    VARRAY_GENERIC_PTR_INIT (used_temp_slots, 3, "used_temp_slots");
-
-  while (level >= (int) VARRAY_ACTIVE_SIZE (used_temp_slots))
-    VARRAY_PUSH_GENERIC_PTR (used_temp_slots, NULL);
+      VEC_safe_grow (temp_slot_p, gc, used_temp_slots, level + 1);
+      p = VEC_address (temp_slot_p, used_temp_slots);
+      memset (&p[old_length], 0,
+             sizeof (temp_slot_p) * (level + 1 - old_length));
+    }
 
-  return (struct temp_slot **) &VARRAY_GENERIC_PTR (used_temp_slots, level);
+  return &(VEC_address (temp_slot_p, used_temp_slots)[level]);
 }
 
 /* Returns the maximal temporary slot level.  */
@@ -564,7 +566,7 @@ max_slot_level (void)
   if (!used_temp_slots)
     return -1;
 
-  return VARRAY_ACTIVE_SIZE (used_temp_slots) - 1;
+  return VEC_length (temp_slot_p, used_temp_slots) - 1;
 }
 
 /* Moves temporary slot TEMP to LEVEL.  */
@@ -819,7 +821,6 @@ assign_temp (tree type_or_decl, int keep, int memory_required,
   if (mode == BLKmode || memory_required)
     {
       HOST_WIDE_INT size = int_size_in_bytes (type);
-      tree size_tree;
       rtx tmp;
 
       /* Zero sized arrays are GNU C extension.  Set size to 1 to avoid
@@ -828,20 +829,10 @@ assign_temp (tree type_or_decl, int keep, int memory_required,
        size = 1;
 
       /* Unfortunately, we don't yet know how to allocate variable-sized
-        temporaries.  However, sometimes we have a fixed upper limit on
-        the size (which is stored in TYPE_ARRAY_MAX_SIZE) and can use that
-        instead.  This is the case for Chill variable-sized strings.  */
-      if (size == -1 && TREE_CODE (type) == ARRAY_TYPE
-         && TYPE_ARRAY_MAX_SIZE (type) != NULL_TREE
-         && host_integerp (TYPE_ARRAY_MAX_SIZE (type), 1))
-       size = tree_low_cst (TYPE_ARRAY_MAX_SIZE (type), 1);
-
-      /* If we still haven't been able to get a size, see if the language
-        can compute a maximum size.  */
-      if (size == -1
-         && (size_tree = lang_hooks.types.max_size (type)) != 0
-         && host_integerp (size_tree, 1))
-       size = tree_low_cst (size_tree, 1);
+        temporaries.  However, sometimes we can find a fixed upper limit on
+        the size, so try that instead.  */
+      else if (size == -1)
+       size = max_int_size_in_bytes (type);
 
       /* The size of the temporary may be too large to fit into an integer.  */
       /* ??? Not sure this should happen except for user silliness, so limit
@@ -1758,15 +1749,21 @@ aggregate_value_p (tree exp, tree fntype)
 
   tree type = (TYPE_P (exp)) ? exp : TREE_TYPE (exp);
 
+  /* DECL node associated with FNTYPE when relevant, which we might need to
+     check for by-invisible-reference returns, typically for CALL_EXPR input
+     EXPressions.  */
+  tree fndecl = NULL_TREE;
+  
   if (fntype)
     switch (TREE_CODE (fntype))
       {
       case CALL_EXPR:
-       fntype = get_callee_fndecl (fntype);
-       fntype = fntype ? TREE_TYPE (fntype) : 0;
+       fndecl = get_callee_fndecl (fntype);
+       fntype = fndecl ? TREE_TYPE (fndecl) : 0;
        break;
       case FUNCTION_DECL:
-       fntype = TREE_TYPE (fntype);
+       fndecl = fntype;
+       fntype = TREE_TYPE (fndecl);
        break;
       case FUNCTION_TYPE:
       case METHOD_TYPE:
@@ -1781,11 +1778,23 @@ aggregate_value_p (tree exp, tree fntype)
 
   if (TREE_CODE (type) == VOID_TYPE)
     return 0;
+
   /* If the front end has decided that this needs to be passed by
      reference, do so.  */
   if ((TREE_CODE (exp) == PARM_DECL || TREE_CODE (exp) == RESULT_DECL)
       && DECL_BY_REFERENCE (exp))
     return 1;
+
+  /* If the EXPression is a CALL_EXPR, honor DECL_BY_REFERENCE set on the
+     called function RESULT_DECL, meaning the function returns in memory by
+     invisible reference.  This check lets front-ends not set TREE_ADDRESSABLE
+     on the function type, which used to be the way to request such a return
+     mechanism but might now be causing troubles at gimplification time if
+     temporaries with the function type need to be created.  */
+  if (TREE_CODE (exp) == CALL_EXPR && fndecl && DECL_RESULT (fndecl)
+      && DECL_BY_REFERENCE (DECL_RESULT (fndecl)))
+    return 1;
+      
   if (targetm.calls.return_in_memory (type, fntype))
     return 1;
   /* Types that are TREE_ADDRESSABLE must be constructed in memory,
@@ -5586,23 +5595,34 @@ rest_of_handle_check_leaf_regs (void)
   return 0;
 }
 
-/* Insert a type into the used types hash table.  */
-void
-used_types_insert (tree t, struct function *func)
+/* Insert a TYPE into the used types hash table of CFUN.  */
+static void
+used_types_insert_helper (tree type, struct function *func)
 {
-  if (t != NULL && func != NULL)
+  if (type != NULL && func != NULL)
     {
       void **slot;
 
       if (func->used_types_hash == NULL)
        func->used_types_hash = htab_create_ggc (37, htab_hash_pointer,
-                                            htab_eq_pointer, NULL);
-      slot = htab_find_slot (func->used_types_hash, t, INSERT);
+                                                htab_eq_pointer, NULL);
+      slot = htab_find_slot (func->used_types_hash, type, INSERT);
       if (*slot == NULL)
-       *slot = t;
+       *slot = type;
     }
 }
 
+/* Given a type, insert it into the used hash table in cfun.  */
+void
+used_types_insert (tree t)
+{
+  while (POINTER_TYPE_P (t) || TREE_CODE (t) == ARRAY_TYPE)
+    t = TREE_TYPE (t);
+  t = TYPE_MAIN_VARIANT (t);
+  if (debug_info_level > DINFO_LEVEL_NONE)
+    used_types_insert_helper (t, cfun);
+}
+
 struct tree_opt_pass pass_leaf_regs =
 {
   NULL,                                 /* name */