Workaround binutils PR14342
authorJan Hubicka <jh@suse.cz>
Sat, 10 Aug 2013 20:52:06 +0000 (22:52 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 10 Aug 2013 20:52:06 +0000 (20:52 +0000)
Workaround binutils PR14342
* tree-profile.c (init_ic_make_global_vars): Add LTO path.
(gimple_init_edge_profiler): Likewise.
(gimple_gen_ic_func_profiler): Likewise.

* Makefile.in: Add _gcov_indirect_call_profiler_v2 symbol.
* libgcov.c (L_gcov_indirect_call_profiler): Restore original API.
(L_gcov_indirect_call_profiler_v2): New.

From-SVN: r201648

gcc/ChangeLog
gcc/tree-profile.c
libgcc/ChangeLog
libgcc/Makefile.in
libgcc/libgcov.c

index 3caf0493493d26d3d73a5ee1c76dc41a7e6ff53f..728ea482cc85ebf8f927a68b4f77ba2a705370ad 100644 (file)
@@ -1,3 +1,10 @@
+2013-08-10  Jan Hubicka  <jh@suse.cz>
+
+       Workaround binutils PR14342
+       * tree-profile.c (init_ic_make_global_vars): Add LTO path.
+       (gimple_init_edge_profiler): Likewise.
+       (gimple_gen_ic_func_profiler): Likewise.
+
 2013-08-09  Jan Hubicka  <jh@suse.cz>
 
        * cgraph.c (cgraph_create_edge_1): Clear speculative flag.
index 3a508a00e43fcf4e4a63da2591216a798f72e2dd..c99253718392be786069a9626f1fa506a44a2c12 100644 (file)
@@ -67,13 +67,28 @@ init_ic_make_global_vars (void)
 
   ptr_void = build_pointer_type (void_type_node);
 
-  ic_void_ptr_var
-    = build_decl (UNKNOWN_LOCATION, VAR_DECL,
-                 get_identifier ("__gcov_indirect_call_callee"),
-                 ptr_void);
+  /* Workaround for binutils bug 14342.  Once it is fixed, remove lto path.  */
+  if (flag_lto)
+    {
+      ic_void_ptr_var
+       = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+                     get_identifier ("__gcov_indirect_call_callee_ltopriv"),
+                     ptr_void);
+      TREE_PUBLIC (ic_void_ptr_var) = 1;
+      DECL_COMMON (ic_void_ptr_var) = 1;
+      DECL_VISIBILITY (ic_void_ptr_var) = VISIBILITY_HIDDEN;
+      DECL_VISIBILITY_SPECIFIED (ic_void_ptr_var) = true;
+    }
+  else
+    {
+      ic_void_ptr_var
+       = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+                     get_identifier ("__gcov_indirect_call_callee"),
+                     ptr_void);
+      TREE_PUBLIC (ic_void_ptr_var) = 1;
+      DECL_EXTERNAL (ic_void_ptr_var) = 1;
+    }
   TREE_STATIC (ic_void_ptr_var) = 1;
-  TREE_PUBLIC (ic_void_ptr_var) = 1;
-  DECL_EXTERNAL (ic_void_ptr_var) = 1;
   DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
   DECL_INITIAL (ic_void_ptr_var) = NULL;
   if (targetm.have_tls)
@@ -83,13 +98,28 @@ init_ic_make_global_vars (void)
   varpool_finalize_decl (ic_void_ptr_var);
 
   gcov_type_ptr = build_pointer_type (get_gcov_type ());
-  ic_gcov_type_ptr_var
-    = build_decl (UNKNOWN_LOCATION, VAR_DECL,
-                 get_identifier ("__gcov_indirect_call_counters"),
-                 gcov_type_ptr);
+  /* Workaround for binutils bug 14342.  Once it is fixed, remove lto path.  */
+  if (flag_lto)
+    {
+      ic_gcov_type_ptr_var
+       = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+                     get_identifier ("__gcov_indirect_call_counters_ltopriv"),
+                     gcov_type_ptr);
+      TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
+      DECL_COMMON (ic_gcov_type_ptr_var) = 1;
+      DECL_VISIBILITY (ic_gcov_type_ptr_var) = VISIBILITY_HIDDEN;
+      DECL_VISIBILITY_SPECIFIED (ic_gcov_type_ptr_var) = true;
+    }
+  else
+    {
+      ic_gcov_type_ptr_var
+       = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+                     get_identifier ("__gcov_indirect_call_counters"),
+                     gcov_type_ptr);
+      TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
+      DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
+    }
   TREE_STATIC (ic_gcov_type_ptr_var) = 1;
-  TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
-  DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
   DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
   DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
   if (targetm.have_tls)
@@ -157,15 +187,31 @@ gimple_init_edge_profiler (void)
 
       init_ic_make_global_vars ();
 
-      /* void (*) (gcov_type, void *)  */
-      ic_profiler_fn_type
-              = build_function_type_list (void_type_node,
-                                         gcov_type_node,
-                                         ptr_void,
-                                         NULL_TREE);
-      tree_indirect_call_profiler_fn
-             = build_fn_decl ("__gcov_indirect_call_profiler_v2",
-                                    ic_profiler_fn_type);
+      /* Workaround for binutils bug 14342.  Once it is fixed, remove lto path.  */
+      if (flag_lto)
+        {
+         /* void (*) (gcov_type, void *)  */
+         ic_profiler_fn_type
+                  = build_function_type_list (void_type_node,
+                                             gcov_type_ptr, gcov_type_node,
+                                             ptr_void, ptr_void,
+                                             NULL_TREE);
+         tree_indirect_call_profiler_fn
+                 = build_fn_decl ("__gcov_indirect_call_profiler",
+                                        ic_profiler_fn_type);
+        }
+      else
+        {
+         /* void (*) (gcov_type, void *)  */
+         ic_profiler_fn_type
+                  = build_function_type_list (void_type_node,
+                                             gcov_type_node,
+                                             ptr_void,
+                                             NULL_TREE);
+         tree_indirect_call_profiler_fn
+                 = build_fn_decl ("__gcov_indirect_call_profiler_v2",
+                                        ic_profiler_fn_type);
+        }
       TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
       DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
        = tree_cons (get_identifier ("leaf"), NULL,
@@ -375,8 +421,25 @@ gimple_gen_ic_func_profiler (void)
                                       true, GSI_SAME_STMT);
   tree_uid = build_int_cst
              (gcov_type_node, cgraph_get_node (current_function_decl)->profile_id);
-  stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
-                            tree_uid, cur_func);
+  /* Workaround for binutils bug 14342.  Once it is fixed, remove lto path.  */
+  if (flag_lto)
+    {
+      tree counter_ptr, ptr_var;
+      counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var,
+                                             true, NULL_TREE, true,
+                                             GSI_SAME_STMT);
+      ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var,
+                                         true, NULL_TREE, true,
+                                         GSI_SAME_STMT);
+
+      stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
+                                counter_ptr, tree_uid, cur_func, ptr_var);
+    }
+  else
+    {
+      stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
+                                tree_uid, cur_func);
+    }
   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
 
   /* Set __gcov_indirect_call_callee to 0,
index f098a42ba6c2519dbf56769b6edb4f47de48bed5..438514fae4484dd2740f0813bd199fbc33669e5b 100644 (file)
@@ -1,3 +1,10 @@
+2013-08-10  Jan Hubicka  <jh@suse.cz>
+
+       Work around binutils PR14342
+       * Makefile.in: Add _gcov_indirect_call_profiler_v2 symbol.
+       * libgcov.c (L_gcov_indirect_call_profiler): Restore original API.
+       (L_gcov_indirect_call_profiler_v2): New.
+
 2013-08-06  Jan Hubicka  <jh@suse.cz>
 
        * libgcov.c (__gcov_indirect_call_callee,
index 63fd626da40fef34e0ae539ba84759c00eb8894b..354fb72d9845eeae351af9d2757a1c22ee51d44f 100644 (file)
@@ -858,7 +858,7 @@ LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta \
     _gcov_execv _gcov_execvp _gcov_execve _gcov_reset _gcov_dump \
     _gcov_interval_profiler _gcov_pow2_profiler _gcov_one_value_profiler \
     _gcov_indirect_call_profiler _gcov_average_profiler _gcov_ior_profiler \
-    _gcov_merge_ior
+    _gcov_merge_ior _gcov_indirect_call_profiler_v2
 
 libgcov-objects = $(patsubst %,%$(objext),$(LIBGCOV))
 
index 93b8bd999631a41f981482bed4deb7eac7e48b92..d1a989274f4a314e250aa530856319a453957f8f 100644 (file)
@@ -1120,6 +1120,42 @@ __gcov_one_value_profiler (gcov_type *counters, gcov_type value)
 #endif
 
 #ifdef L_gcov_indirect_call_profiler
+/* This function exist only for workaround of binutils bug 14342.
+   Once this compatibility hack is obsolette, it can be removed.  */
+
+/* By default, the C++ compiler will use function addresses in the
+   vtable entries.  Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
+   tells the compiler to use function descriptors instead.  The value
+   of this macro says how many words wide the descriptor is (normally 2),
+   but it may be dependent on target flags.  Since we do not have access
+   to the target flags here we just check to see if it is set and use
+   that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
+
+   It is assumed that the address of a function descriptor may be treated
+   as a pointer to a function.  */
+
+#ifdef TARGET_VTABLE_USES_DESCRIPTORS
+#define VTABLE_USES_DESCRIPTORS 1
+#else
+#define VTABLE_USES_DESCRIPTORS 0
+#endif
+
+/* Tries to determine the most common value among its inputs. */
+void
+__gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
+                               void* cur_func, void* callee_func)
+{
+  /* If the C++ virtual tables contain function descriptors then one
+     function may have multiple descriptors and we need to dereference
+     the descriptors to see if they point to the same function.  */
+  if (cur_func == callee_func
+      || (VTABLE_USES_DESCRIPTORS && callee_func
+          && *(void **) cur_func == *(void **) callee_func))
+    __gcov_one_value_profiler_body (counter, value);
+}
+
+#endif
+#ifdef L_gcov_indirect_call_profiler_v2
 
 /* These two variables are used to actually track caller and callee.  Keep
    them in TLS memory so races are not common (they are written to often).
@@ -1135,7 +1171,6 @@ __thread
 #endif
 gcov_type * __gcov_indirect_call_counters;
 
-
 /* By default, the C++ compiler will use function addresses in the
    vtable entries.  Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
    tells the compiler to use function descriptors instead.  The value
@@ -1167,7 +1202,6 @@ __gcov_indirect_call_profiler_v2 (gcov_type value, void* cur_func)
 }
 #endif
 
-
 #ifdef L_gcov_average_profiler
 /* Increase corresponding COUNTER by VALUE.  FIXME: Perhaps we want
    to saturate up.  */