OSDN Git Service

* config/rs6000/a2.md: Add FSF comment header.
[pf3gnuchains/gcc-fork.git] / gcc / function.c
index b1d467c..35c0cfd 100644 (file)
@@ -130,6 +130,10 @@ static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
 static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
   htab_t epilogue_insn_hash;
 \f
+
+htab_t types_used_by_vars_hash = NULL;
+tree types_used_by_cur_var_decl = NULL;
+
 /* Forward declarations.  */
 
 static struct temp_slot *find_temp_slot_from_address (rtx);
@@ -1775,8 +1779,11 @@ instantiate_virtual_regs (void)
            || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
            || GET_CODE (PATTERN (insn)) == ASM_INPUT)
          continue;
-
-       instantiate_virtual_regs_in_insn (insn);
+       else if (DEBUG_INSN_P (insn))
+         for_each_rtx (&INSN_VAR_LOCATION (insn),
+                       instantiate_virtual_regs_in_rtx, NULL);
+       else
+         instantiate_virtual_regs_in_insn (insn);
 
        if (INSN_DELETED_P (insn))
          continue;
@@ -2430,20 +2437,25 @@ assign_parm_find_stack_rtl (tree parm, struct assign_parm_data_one *data)
     stack_parm = gen_rtx_PLUS (Pmode, stack_parm, offset_rtx);
   stack_parm = gen_rtx_MEM (data->promoted_mode, stack_parm);
 
-  set_mem_attributes (stack_parm, parm, 1);
-  /* set_mem_attributes could set MEM_SIZE to the passed mode's size,
-     while promoted mode's size is needed.  */
-  if (data->promoted_mode != BLKmode
-      && data->promoted_mode != DECL_MODE (parm))
+  if (!data->passed_pointer)
     {
-      set_mem_size (stack_parm, GEN_INT (GET_MODE_SIZE (data->promoted_mode)));
-      if (MEM_EXPR (stack_parm) && MEM_OFFSET (stack_parm))
+      set_mem_attributes (stack_parm, parm, 1);
+      /* set_mem_attributes could set MEM_SIZE to the passed mode's size,
+        while promoted mode's size is needed.  */
+      if (data->promoted_mode != BLKmode
+         && data->promoted_mode != DECL_MODE (parm))
        {
-         int offset = subreg_lowpart_offset (DECL_MODE (parm),
-                                             data->promoted_mode);
-         if (offset)
-           set_mem_offset (stack_parm,
-                           plus_constant (MEM_OFFSET (stack_parm), -offset));
+         set_mem_size (stack_parm,
+                       GEN_INT (GET_MODE_SIZE (data->promoted_mode)));
+         if (MEM_EXPR (stack_parm) && MEM_OFFSET (stack_parm))
+           {
+             int offset = subreg_lowpart_offset (DECL_MODE (parm),
+                                                 data->promoted_mode);
+             if (offset)
+               set_mem_offset (stack_parm,
+                               plus_constant (MEM_OFFSET (stack_parm),
+                                              -offset));
+           }
        }
     }
 
@@ -4445,13 +4457,21 @@ expand_function_start (tree subr)
   if (cfun->static_chain_decl)
     {
       tree parm = cfun->static_chain_decl;
-      rtx local = gen_reg_rtx (Pmode);
+      rtx local, chain, insn;
+
+      local = gen_reg_rtx (Pmode);
+      chain = targetm.calls.static_chain (current_function_decl, true);
 
-      set_decl_incoming_rtl (parm, static_chain_incoming_rtx, false);
+      set_decl_incoming_rtl (parm, chain, false);
       SET_DECL_RTL (parm, local);
       mark_reg_pointer (local, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm))));
 
-      emit_move_insn (local, static_chain_incoming_rtx);
+      insn = emit_move_insn (local, chain);
+
+      /* Mark the register as eliminable, similar to parameters.  */
+      if (MEM_P (chain)
+         && reg_mentioned_p (arg_pointer_rtx, XEXP (chain, 0)))
+       set_unique_reg_note (insn, REG_EQUIV, chain);
     }
 
   /* If the function receives a non-local goto, then store the
@@ -5395,6 +5415,8 @@ reposition_prologue_and_epilogue_notes (void)
 const char *
 current_function_name (void)
 {
+  if (cfun == NULL)
+    return "<none>";
   return lang_hooks.decl_printable_name (cfun->decl, 2);
 }
 \f
@@ -5410,6 +5432,7 @@ rest_of_handle_check_leaf_regs (void)
 }
 
 /* Insert a TYPE into the used types hash table of CFUN.  */
+
 static void
 used_types_insert_helper (tree type, struct function *func)
 {
@@ -5434,7 +5457,81 @@ used_types_insert (tree t)
     t = TREE_TYPE (t);
   t = TYPE_MAIN_VARIANT (t);
   if (debug_info_level > DINFO_LEVEL_NONE)
-    used_types_insert_helper (t, cfun);
+    {
+      if (cfun)
+       used_types_insert_helper (t, cfun);
+      else
+       /* So this might be a type referenced by a global variable.
+          Record that type so that we can later decide to emit its debug
+          information.  */
+       types_used_by_cur_var_decl =
+         tree_cons (t, NULL, types_used_by_cur_var_decl);
+
+    }
+}
+
+/* Helper to Hash a struct types_used_by_vars_entry.  */
+
+static hashval_t
+hash_types_used_by_vars_entry (const struct types_used_by_vars_entry *entry)
+{
+  gcc_assert (entry && entry->var_decl && entry->type);
+
+  return iterative_hash_object (entry->type,
+                               iterative_hash_object (entry->var_decl, 0));
+}
+
+/* Hash function of the types_used_by_vars_entry hash table.  */
+
+hashval_t
+types_used_by_vars_do_hash (const void *x)
+{
+  const struct types_used_by_vars_entry *entry =
+    (const struct types_used_by_vars_entry *) x;
+
+  return hash_types_used_by_vars_entry (entry);
+}
+
+/*Equality function of the types_used_by_vars_entry hash table.  */
+
+int
+types_used_by_vars_eq (const void *x1, const void *x2)
+{
+  const struct types_used_by_vars_entry *e1 =
+    (const struct types_used_by_vars_entry *) x1;
+  const struct types_used_by_vars_entry *e2 =
+    (const struct types_used_by_vars_entry *)x2;
+
+  return (e1->var_decl == e2->var_decl && e1->type == e2->type);
+}
+
+/* Inserts an entry into the types_used_by_vars_hash hash table. */
+
+void
+types_used_by_var_decl_insert (tree type, tree var_decl)
+{
+  if (type != NULL && var_decl != NULL)
+    {
+      void **slot;
+      struct types_used_by_vars_entry e;
+      e.var_decl = var_decl;
+      e.type = type;
+      if (types_used_by_vars_hash == NULL)
+       types_used_by_vars_hash =
+         htab_create_ggc (37, types_used_by_vars_do_hash,
+                          types_used_by_vars_eq, NULL);
+      slot = htab_find_slot_with_hash (types_used_by_vars_hash, &e,
+                                      hash_types_used_by_vars_entry (&e), INSERT);
+      if (*slot == NULL)
+       {
+         struct types_used_by_vars_entry *entry;
+         entry = (struct types_used_by_vars_entry*) ggc_alloc
+                   (sizeof (struct types_used_by_vars_entry));
+         entry->type = type;
+         entry->var_decl = var_decl;
+         *slot = entry;
+       }
+    }
 }
 
 struct rtl_opt_pass pass_leaf_regs =