OSDN Git Service

2004-11-01 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / function.c
index a8bd0f5..82776e7 100644 (file)
@@ -1343,10 +1343,20 @@ instantiate_decl (rtx x, HOST_WIDE_INT size, int valid_only)
   enum machine_mode mode;
   rtx addr;
 
+  if (x == 0)
+    return;
+
+  /* If this is a CONCAT, recurse for the pieces.  */
+  if (GET_CODE (x) == CONCAT)
+    {
+      instantiate_decl (XEXP (x, 0), size / 2, valid_only);
+      instantiate_decl (XEXP (x, 1), size / 2, valid_only);
+      return;
+    }
+
   /* If this is not a MEM, no need to do anything.  Similarly if the
      address is a constant or a register that is not a virtual register.  */
-
-  if (x == 0 || !MEM_P (x))
+  if (!MEM_P (x))
     return;
 
   addr = XEXP (x, 0);
@@ -2540,8 +2550,28 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
     {
       rtx parmreg = gen_reg_rtx (data->nominal_mode);
 
-      emit_group_store (parmreg, entry_parm, data->nominal_type,
-                       int_size_in_bytes (data->nominal_type));
+      /* For values returned in multiple registers, handle possible
+        incompatible calls to emit_group_store.
+
+        For example, the following would be invalid, and would have to
+        be fixed by the conditional below:
+
+          emit_group_store ((reg:SF), (parallel:DF))
+          emit_group_store ((reg:SI), (parallel:DI))
+
+        An example of this are doubles in e500 v2:
+          (parallel:DF (expr_list (reg:SI) (const_int 0))
+                       (expr_list (reg:SI) (const_int 4))).  */
+      if (data->nominal_mode != data->passed_mode)
+       {
+         rtx t = gen_reg_rtx (GET_MODE (entry_parm));
+         emit_group_store (t, entry_parm, NULL_TREE,
+                           GET_MODE_SIZE (GET_MODE (entry_parm)));
+         convert_move (parmreg, t, 0);
+       }
+      else
+       emit_group_store (parmreg, entry_parm, data->nominal_type,
+                         int_size_in_bytes (data->nominal_type));
       SET_DECL_RTL (parm, parmreg);
       return;
     }
@@ -2720,7 +2750,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
 
       /* TREE_USED gets set erroneously during expand_assignment.  */
       save_tree_used = TREE_USED (parm);
-      expand_assignment (parm, make_tree (data->nominal_type, tempreg), 0);
+      expand_assignment (parm, make_tree (data->nominal_type, tempreg));
       TREE_USED (parm) = save_tree_used;
       all->conversion_insns = get_insns ();
       end_sequence ();