calls.c (emit_call_1): Set MEM_EXPR on call's MEM.
authorJakub Jelinek <jakub@redhat.com>
Wed, 16 Mar 2011 08:36:42 +0000 (09:36 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 16 Mar 2011 08:36:42 +0000 (09:36 +0100)
* calls.c (emit_call_1): Set MEM_EXPR on call's MEM.
* var-tracking.c (prepare_call_arguments): Use MEM_EXPR on
call's MEM.  Handle functions returning aggregate through a hidden
first pointer.  For virtual calls add clobbered pc to call arguments
chain.
* dwarf2out.c (gen_subprogram_die): Emit
DW_AT_GNU_call_site_target_clobbered if DW_AT_GNU_call_site_target
can't be emitted.

From-SVN: r171036

gcc/ChangeLog
gcc/calls.c
gcc/dwarf2out.c
gcc/var-tracking.c

index ea855fe905c3cc905414ed6721bf995738356fad..e3934df4e22c8b0f552254e2bda0425461fa5ac4 100644 (file)
@@ -1,5 +1,14 @@
 2011-03-16  Jakub Jelinek  <jakub@redhat.com>
 
+       * calls.c (emit_call_1): Set MEM_EXPR on call's MEM.
+       * var-tracking.c (prepare_call_arguments): Use MEM_EXPR on
+       call's MEM.  Handle functions returning aggregate through a hidden
+       first pointer.  For virtual calls add clobbered pc to call arguments
+       chain.
+       * dwarf2out.c (gen_subprogram_die): Emit
+       DW_AT_GNU_call_site_target_clobbered if DW_AT_GNU_call_site_target
+       can't be emitted.
+
        PR debug/45882
        * rtl.def (ENTRY_VALUE): Change format from "e" to "0".
        * rtl.h (ENTRY_VALUE_EXP): Define.
index b15bfefa3c1d9a9e071aed3d202b5e2be39d18d7..fe99bc065e354bc463ad10081d698a1470b83b79 100644 (file)
@@ -256,7 +256,7 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
             CUMULATIVE_ARGS *args_so_far ATTRIBUTE_UNUSED)
 {
   rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
-  rtx call_insn;
+  rtx call_insn, call, funmem;
   int already_popped = 0;
   HOST_WIDE_INT n_popped
     = targetm.calls.return_pops_args (fndecl, funtype, stack_size);
@@ -271,6 +271,12 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
   if (GET_CODE (funexp) != SYMBOL_REF)
     funexp = memory_address (FUNCTION_MODE, funexp);
 
+  funmem = gen_rtx_MEM (FUNCTION_MODE, funexp);
+  if (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL)
+    set_mem_expr (funmem, fndecl);
+  else if (fntree)
+    set_mem_expr (funmem, build_fold_indirect_ref (CALL_EXPR_FN (fntree)));
+
 #if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop)
   if ((ecf_flags & ECF_SIBCALL)
       && HAVE_sibcall_pop && HAVE_sibcall_value_pop
@@ -283,13 +289,11 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
         if possible, for the sake of frame pointer elimination.  */
 
       if (valreg)
-       pat = GEN_SIBCALL_VALUE_POP (valreg,
-                                    gen_rtx_MEM (FUNCTION_MODE, funexp),
-                                    rounded_stack_size_rtx, next_arg_reg,
-                                    n_pop);
+       pat = GEN_SIBCALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx,
+                                    next_arg_reg, n_pop);
       else
-       pat = GEN_SIBCALL_POP (gen_rtx_MEM (FUNCTION_MODE, funexp),
-                              rounded_stack_size_rtx, next_arg_reg, n_pop);
+       pat = GEN_SIBCALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg,
+                              n_pop);
 
       emit_call_insn (pat);
       already_popped = 1;
@@ -316,12 +320,11 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
         if possible, for the sake of frame pointer elimination.  */
 
       if (valreg)
-       pat = GEN_CALL_VALUE_POP (valreg,
-                                 gen_rtx_MEM (FUNCTION_MODE, funexp),
-                                 rounded_stack_size_rtx, next_arg_reg, n_pop);
+       pat = GEN_CALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx,
+                                 next_arg_reg, n_pop);
       else
-       pat = GEN_CALL_POP (gen_rtx_MEM (FUNCTION_MODE, funexp),
-                           rounded_stack_size_rtx, next_arg_reg, n_pop);
+       pat = GEN_CALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg,
+                           n_pop);
 
       emit_call_insn (pat);
       already_popped = 1;
@@ -334,13 +337,12 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
       && HAVE_sibcall && HAVE_sibcall_value)
     {
       if (valreg)
-       emit_call_insn (GEN_SIBCALL_VALUE (valreg,
-                                          gen_rtx_MEM (FUNCTION_MODE, funexp),
+       emit_call_insn (GEN_SIBCALL_VALUE (valreg, funmem,
                                           rounded_stack_size_rtx,
                                           next_arg_reg, NULL_RTX));
       else
-       emit_call_insn (GEN_SIBCALL (gen_rtx_MEM (FUNCTION_MODE, funexp),
-                                    rounded_stack_size_rtx, next_arg_reg,
+       emit_call_insn (GEN_SIBCALL (funmem, rounded_stack_size_rtx,
+                                    next_arg_reg,
                                     GEN_INT (struct_value_size)));
     }
   else
@@ -350,13 +352,10 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
   if (HAVE_call && HAVE_call_value)
     {
       if (valreg)
-       emit_call_insn (GEN_CALL_VALUE (valreg,
-                                       gen_rtx_MEM (FUNCTION_MODE, funexp),
-                                       rounded_stack_size_rtx, next_arg_reg,
-                                       NULL_RTX));
+       emit_call_insn (GEN_CALL_VALUE (valreg, funmem, rounded_stack_size_rtx,
+                                       next_arg_reg, NULL_RTX));
       else
-       emit_call_insn (GEN_CALL (gen_rtx_MEM (FUNCTION_MODE, funexp),
-                                 rounded_stack_size_rtx, next_arg_reg,
+       emit_call_insn (GEN_CALL (funmem, rounded_stack_size_rtx, next_arg_reg,
                                  GEN_INT (struct_value_size)));
     }
   else
@@ -366,6 +365,19 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
   /* Find the call we just emitted.  */
   call_insn = last_call_insn ();
 
+  /* Some target create a fresh MEM instead of reusing the one provided
+     above.  Set its MEM_EXPR.  */
+  call = PATTERN (call_insn);
+  if (GET_CODE (call) == PARALLEL)
+    call = XVECEXP (call, 0, 0);
+  if (GET_CODE (call) == SET)
+    call = SET_SRC (call);
+  if (GET_CODE (call) == CALL
+      && MEM_P (XEXP (call, 0))
+      && MEM_EXPR (XEXP (call, 0)) == NULL_TREE
+      && MEM_EXPR (funmem) != NULL_TREE)
+    set_mem_expr (XEXP (call, 0), MEM_EXPR (funmem));
+
   /* Put the register usage information there.  */
   add_function_usage_to (call_insn, call_fusage);
 
index b4bca7858324e7d8bad10f88ea5cebc1cdda54b5..38b1422d40f403cba37f921b7df5802b1a51dad0 100644 (file)
@@ -19615,7 +19615,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
          for (ca_loc = call_arg_locations; ca_loc; ca_loc = ca_loc->next)
            {
              dw_die_ref die = NULL;
-             rtx tloc = NULL_RTX;
+             rtx tloc = NULL_RTX, tlocc = NULL_RTX;
              rtx arg, next_arg;
 
              for (arg = NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note);
@@ -19644,6 +19644,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                      tloc = XEXP (XEXP (arg, 0), 1);
                      continue;
                    }
+                 else if (GET_CODE (XEXP (XEXP (arg, 0), 0)) == CLOBBER
+                          && XEXP (XEXP (XEXP (arg, 0), 0), 0) == pc_rtx)
+                   {
+                     gcc_assert (ca_loc->symbol_ref == NULL_RTX);
+                     tlocc = XEXP (XEXP (arg, 0), 1);
+                     continue;
+                   }
                  if (REG_P (XEXP (XEXP (arg, 0), 0)))
                    reg = reg_loc_descriptor (XEXP (XEXP (arg, 0), 0),
                                              VAR_INIT_STATUS_INITIALIZED);
@@ -19677,13 +19684,23 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
              if (die == NULL
                  && (ca_loc->symbol_ref || tloc))
                die = gen_call_site_die (decl, subr_die, ca_loc);
-             if (die != NULL && tloc != NULL_RTX)
+             if (die != NULL && (tloc != NULL_RTX || tlocc != NULL_RTX))
                {
-                 dw_loc_descr_ref tval
-                   = mem_loc_descriptor (tloc, VOIDmode,
-                                         VAR_INIT_STATUS_INITIALIZED);
+                 dw_loc_descr_ref tval = NULL;
+
+                 if (tloc != NULL_RTX)
+                   tval = mem_loc_descriptor (tloc, VOIDmode,
+                                              VAR_INIT_STATUS_INITIALIZED);
                  if (tval)
                    add_AT_loc (die, DW_AT_GNU_call_site_target, tval);
+                 else if (tlocc != NULL_RTX)
+                   {
+                     tval = mem_loc_descriptor (tlocc, VOIDmode,
+                                                VAR_INIT_STATUS_INITIALIZED);
+                     if (tval)
+                       add_AT_loc (die, DW_AT_GNU_call_site_target_clobbered,
+                                   tval);
+                   }
                }
              if (die != NULL)
                {
index 50890d8c0ccd5945e89b17915a2ef1dca9066083..ee180f13f622d95404705cbc1e73719780af716e 100644 (file)
@@ -5576,7 +5576,9 @@ prepare_call_arguments (basic_block bb, rtx insn)
   rtx link, x;
   rtx prev, cur, next;
   rtx call = PATTERN (insn);
-  tree type = NULL_TREE, t;
+  rtx this_arg = NULL_RTX;
+  tree type = NULL_TREE, t, fndecl = NULL_TREE;
+  tree obj_type_ref = NULL_TREE;
   CUMULATIVE_ARGS args_so_far;
 
   memset (&args_so_far, 0, sizeof (args_so_far));
@@ -5584,27 +5586,91 @@ prepare_call_arguments (basic_block bb, rtx insn)
     call = XVECEXP (call, 0, 0);
   if (GET_CODE (call) == SET)
     call = SET_SRC (call);
-  if (GET_CODE (call) == CALL
-      && MEM_P (XEXP (call, 0))
-      && GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
-    {
-      rtx symbol = XEXP (XEXP (call, 0), 0);
-      if (SYMBOL_REF_DECL (symbol)
-         && TREE_CODE (SYMBOL_REF_DECL (symbol)) == FUNCTION_DECL
-         && TYPE_ARG_TYPES (TREE_TYPE (SYMBOL_REF_DECL (symbol))))
+  if (GET_CODE (call) == CALL && MEM_P (XEXP (call, 0)))
+    {
+      if (GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
+       {
+         rtx symbol = XEXP (XEXP (call, 0), 0);
+         if (SYMBOL_REF_DECL (symbol))
+           fndecl = SYMBOL_REF_DECL (symbol);
+       }
+      if (fndecl == NULL_TREE)
+       fndecl = MEM_EXPR (XEXP (call, 0));
+      if (fndecl
+         && TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE
+         && TREE_CODE (TREE_TYPE (fndecl)) != METHOD_TYPE)
+       fndecl = NULL_TREE;
+      if (fndecl && TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+       type = TREE_TYPE (fndecl);
+      if (fndecl && TREE_CODE (fndecl) != FUNCTION_DECL)
+       {
+         if (TREE_CODE (fndecl) == INDIRECT_REF
+             && TREE_CODE (TREE_OPERAND (fndecl, 0)) == OBJ_TYPE_REF)
+           obj_type_ref = TREE_OPERAND (fndecl, 0);
+         fndecl = NULL_TREE;
+       }
+      if (type)
        {
-         type = TREE_TYPE (SYMBOL_REF_DECL (symbol));
          for (t = TYPE_ARG_TYPES (type); t && t != void_list_node;
               t = TREE_CHAIN (t))
            if (TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
                && INTEGRAL_TYPE_P (TREE_TYPE (TREE_VALUE (t))))
              break;
-         if (t == NULL || t == void_list_node)
+         if ((t == NULL || t == void_list_node) && obj_type_ref == NULL_TREE)
            type = NULL;
          else
-           INIT_CUMULATIVE_ARGS (args_so_far, type, NULL_RTX,
-                                 SYMBOL_REF_DECL (symbol),
-                                 list_length (TYPE_ARG_TYPES (type)));
+           {
+             int nargs = list_length (TYPE_ARG_TYPES (type));
+             link = CALL_INSN_FUNCTION_USAGE (insn);
+#ifndef PCC_STATIC_STRUCT_RETURN
+             if (aggregate_value_p (TREE_TYPE (type), type)
+                 && targetm.calls.struct_value_rtx (type, 0) == 0)
+               {
+                 tree struct_addr = build_pointer_type (TREE_TYPE (type));
+                 enum machine_mode mode = TYPE_MODE (struct_addr);
+                 rtx reg;
+                 INIT_CUMULATIVE_ARGS (args_so_far, type, NULL_RTX, fndecl,
+                                       nargs + 1);
+                 reg = targetm.calls.function_arg (&args_so_far, mode,
+                                                   struct_addr, true);
+                 targetm.calls.function_arg_advance (&args_so_far, mode,
+                                                     struct_addr, true);
+                 if (reg == NULL_RTX)
+                   {
+                     for (; link; link = XEXP (link, 1))
+                       if (GET_CODE (XEXP (link, 0)) == USE
+                           && MEM_P (XEXP (XEXP (link, 0), 0)))
+                         {
+                           link = XEXP (link, 1);
+                           break;
+                         }
+                   }
+               }
+#endif
+             else
+               INIT_CUMULATIVE_ARGS (args_so_far, type, NULL_RTX, fndecl,
+                                     nargs);
+             if (obj_type_ref && TYPE_ARG_TYPES (type) != void_list_node)
+               {
+                 enum machine_mode mode;
+                 t = TYPE_ARG_TYPES (type);
+                 mode = TYPE_MODE (TREE_VALUE (t));
+                 this_arg = targetm.calls.function_arg (&args_so_far, mode,
+                                                        TREE_VALUE (t), true);
+                 if (this_arg && !REG_P (this_arg))
+                   this_arg = NULL_RTX;
+                 else if (this_arg == NULL_RTX)
+                   {
+                     for (; link; link = XEXP (link, 1))
+                       if (GET_CODE (XEXP (link, 0)) == USE
+                           && MEM_P (XEXP (XEXP (link, 0), 0)))
+                         {
+                           this_arg = XEXP (XEXP (link, 0), 0);
+                           break;
+                         }
+                   }
+               }
+           }
        }
     }
   t = type ? TYPE_ARG_TYPES (type) : NULL_TREE;
@@ -5752,6 +5818,20 @@ prepare_call_arguments (basic_block bb, rtx insn)
            }
        }
     }
+  if (this_arg)
+    {
+      enum machine_mode mode
+       = TYPE_MODE (TREE_TYPE (OBJ_TYPE_REF_EXPR (obj_type_ref)));
+      rtx clobbered = gen_rtx_MEM (mode, this_arg);
+      HOST_WIDE_INT token
+       = tree_low_cst (OBJ_TYPE_REF_TOKEN (obj_type_ref), 0);
+      if (token)
+       clobbered = plus_constant (clobbered, token * GET_MODE_SIZE (mode));
+      clobbered = gen_rtx_MEM (mode, clobbered);
+      x = gen_rtx_CONCAT (mode, gen_rtx_CLOBBER (VOIDmode, pc_rtx), clobbered);
+      call_arguments
+       = gen_rtx_EXPR_LIST (VOIDmode, x, call_arguments);
+    }
 }
 
 /* Callback for cselib_record_sets_hook, that records as micro