re PR lto/67548 (LTO drops weak binding with "ld -r")
authorJan Hubicka <jh@suse.cz>
Wed, 25 Nov 2015 23:05:07 +0000 (00:05 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 25 Nov 2015 23:05:07 +0000 (23:05 +0000)
PR lto/67548
* lto-plugin.c (linker_output, linker_output_set): New statics.
(all_symbols_read_handler): Add -flinker-output option.
(onload): Record linker_output info.

* ipa-visibility.c (cgraph_externally_visible_p,
varpool_node::externally_visible_p): When doing incremental linking,
hidden symbols may be still used later.
(update_visibility_by_resolution_info): Do not drop weak during
incremental link.
(function_and_variable_visibility): Fix formating.
* flag-types.h (lto_linker_output): Declare.
* common.opt 9flag_incremental_link): New flag.

* lto-lang.c (lto_post_options): Process flag_lto_linker_output.
* lang.opt (lto_linker_output): New enum.
(flinker_output): New flag.

From-SVN: r230915

gcc/ChangeLog
gcc/common.opt
gcc/flag-types.h
gcc/ipa-visibility.c
gcc/lto/ChangeLog
gcc/lto/lang.opt
gcc/lto/lto-lang.c
lto-plugin/ChangeLog
lto-plugin/lto-plugin.c

index e8687950798ada736da7290bb689ee73250cb3c7..eae18834bd06cfb240a9061005db7454e6ac1216 100644 (file)
@@ -1,3 +1,14 @@
+2015-11-25  Jan Hubicka  <jh@suse.cz>
+
+       * ipa-visibility.c (cgraph_externally_visible_p,
+       varpool_node::externally_visible_p): When doing incremental linking,
+       hidden symbols may be still used later.
+       (update_visibility_by_resolution_info): Do not drop weak during
+       incremental link.
+       (function_and_variable_visibility): Fix formating.
+       * flag-types.h (lto_linker_output): Declare.
+       * common.opt 9flag_incremental_link): New flag.
+
 2015-11-25  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        * config/rs6000/constraints.md (wb constraint): New constraint for
index 3eb520eaef2e72c2fb67d1df75047cd6956b2f64..e1617c41bd819451e41819030d2369e53796b2d3 100644 (file)
@@ -46,6 +46,12 @@ int optimize_fast
 Variable
 bool in_lto_p = false
 
+; This variable is set to non-0 only by LTO front-end.  1 indicates that
+; the output produced will be used for incrmeental linking (thus weak symbols
+; can still be bound).
+Variable
+int flag_incremental_link = 0
+
 ; 0 means straightforward implementation of complex divide acceptable.
 ; 1 means wide ranges of inputs must work for complex divide.
 ; 2 means C99-like requirements for complex multiply and divide.
index 88a760c5d4e271849e62fde3e2504a6671646b30..b130fc5806a53251bc31dad9b1152fd995a5c543 100644 (file)
@@ -265,6 +265,14 @@ enum lto_partition_model {
   LTO_PARTITION_MAX = 4
 };
 
+/* flag_lto_linker_output initialization values.  */
+enum lto_linker_output {
+  LTO_LINKER_OUTPUT_UNKNOWN,
+  LTO_LINKER_OUTPUT_REL,
+  LTO_LINKER_OUTPUT_DYN,
+  LTO_LINKER_OUTPUT_PIE,
+  LTO_LINKER_OUTPUT_EXEC
+};
 
 /* gfortran -finit-real= values.  */
 
index d128ca85f1c684ce93a8033fe7d05eca87452091..41ed4db67459d4fcc0ededa4b8ed3ab3929d7719 100644 (file)
@@ -217,13 +217,13 @@ cgraph_externally_visible_p (struct cgraph_node *node,
      This improves code quality and we know we will duplicate them at most twice
      (in the case that we are not using plugin and link with object file
       implementing same COMDAT)  */
-  if ((in_lto_p || whole_program)
+  if (((in_lto_p || whole_program) && !flag_incremental_link)
       && DECL_COMDAT (node->decl)
       && comdat_can_be_unshared_p (node))
     return false;
 
   /* When doing link time optimizations, hidden symbols become local.  */
-  if (in_lto_p
+  if ((in_lto_p && !flag_incremental_link)
       && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
          || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL)
       /* Be sure that node is defined in IR file, not in other object
@@ -293,13 +293,13 @@ varpool_node::externally_visible_p (void)
      so this does not enable more optimization, but referring static var
      is faster for dynamic linking.  Also this match logic hidding vtables
      from LTO symbol tables.  */
-  if ((in_lto_p || flag_whole_program)
+  if (((in_lto_p || flag_whole_program) && !flag_incremental_link)
       && DECL_COMDAT (decl)
       && comdat_can_be_unshared_p (this))
     return false;
 
   /* When doing link time optimizations, hidden symbols become local.  */
-  if (in_lto_p
+  if (in_lto_p && !flag_incremental_link
       && (DECL_VISIBILITY (decl) == VISIBILITY_HIDDEN
          || DECL_VISIBILITY (decl) == VISIBILITY_INTERNAL)
       /* Be sure that node is defined in IR file, not in other object
@@ -405,17 +405,36 @@ update_visibility_by_resolution_info (symtab_node * node)
     for (symtab_node *next = node->same_comdat_group;
         next != node; next = next->same_comdat_group)
       {
-       next->set_comdat_group (NULL);
-       DECL_WEAK (next->decl) = false;
+       /* During incremental linking we need to keep symbol weak for future
+          linking.  We can still drop definition if we know non-LTO world
+          prevails.  */
+       if (!flag_incremental_link)
+         {
+           DECL_WEAK (next->decl) = false;
+           next->set_comdat_group (NULL);
+         }
        if (next->externally_visible
            && !define)
-         DECL_EXTERNAL (next->decl) = true;
+         {
+           DECL_EXTERNAL (next->decl) = true;
+           next->set_comdat_group (NULL);
+         }
       }
-  node->set_comdat_group (NULL);
-  DECL_WEAK (node->decl) = false;
+
+  /* During incremental linking we need to keep symbol weak for future
+     linking.  We can still drop definition if we know non-LTO world prevails.  */
+  if (!flag_incremental_link)
+    {
+      DECL_WEAK (node->decl) = false;
+      node->set_comdat_group (NULL);
+      node->dissolve_same_comdat_group_list ();
+    }
   if (!define)
-    DECL_EXTERNAL (node->decl) = true;
-  node->dissolve_same_comdat_group_list ();
+    {
+      DECL_EXTERNAL (node->decl) = true;
+      node->set_comdat_group (NULL);
+      node->dissolve_same_comdat_group_list ();
+    }
 }
 
 /* Decide on visibility of all symbols.  */
@@ -639,8 +658,9 @@ function_and_variable_visibility (bool whole_program)
        {
          gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
          vnode->unique_name = ((vnode->resolution == LDPR_PREVAILING_DEF_IRONLY
-                                      || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
-                                      && TREE_PUBLIC (vnode->decl));
+                                || vnode->resolution
+                                     == LDPR_PREVAILING_DEF_IRONLY_EXP)
+                               && TREE_PUBLIC (vnode->decl));
          if (vnode->same_comdat_group && TREE_PUBLIC (vnode->decl))
            {
              symtab_node *next = vnode;
index 4aae7401fe29967767cd9918c0baf0f933a0242e..1ddacfa158f802126512d13590a2bfa63bdc1a46 100644 (file)
@@ -1,3 +1,9 @@
+2015-11-25  Jan Hubicka  <jh@suse.cz>
+
+       * lto-lang.c (lto_post_options): Process flag_lto_linker_output.
+       * lang.opt (lto_linker_output): New enum.
+       (flinker_output): New flag.
+
 2015-11-24  Jan Hubicka  <hubicka@ucw.cz>
 
        * lto-symtab.c: Include alias.h
index f7aedc4b3e4206acbdfe0e250a70dc18ca58fbbe..c4216b350d0a24b29936fbf12b33bfd884d8fb35 100644 (file)
 Language
 LTO
 
+Enum
+Name(lto_linker_output) Type(enum lto_linker_output) UnknownError(unknown linker output %qs)
+
+EnumValue
+Enum(lto_linker_output) String(unknown) Value(LTO_LINKER_OUTPUT_UNKNOWN)
+
+EnumValue
+Enum(lto_linker_output) String(rel) Value(LTO_LINKER_OUTPUT_REL)
+
+EnumValue
+Enum(lto_linker_output) String(dyn) Value(LTO_LINKER_OUTPUT_DYN)
+
+EnumValue
+Enum(lto_linker_output) String(pie) Value(LTO_LINKER_OUTPUT_PIE)
+
+EnumValue
+Enum(lto_linker_output) String(exec) Value(LTO_LINKER_OUTPUT_EXEC)
+
+flinker-output=
+LTO Report Driver Joined RejectNegative Enum(lto_linker_output) Var(flag_lto_linker_output) Init(LTO_LINKER_OUTPUT_UNKNOWN)
+Set linker output type (used internally during LTO optimization)
+
+
 fltrans
 LTO Report Var(flag_ltrans)
 Run the link-time optimizer in local transformation (LTRANS) mode.
index 53dd8f6df5508730e727da89e99ee2ba5145584c..90bacde7eb5b4961e69064fe190c1df4a54c3f1f 100644 (file)
@@ -819,6 +819,35 @@ lto_post_options (const char **pfilename ATTRIBUTE_UNUSED)
   if (flag_wpa)
     flag_generate_lto = 1;
 
+  /* Initialize the codegen flags according to the output type.  */
+  switch (flag_lto_linker_output)
+    {
+    case LTO_LINKER_OUTPUT_REL: /* .o: incremental link producing LTO IL  */
+      flag_whole_program = 0;
+      flag_incremental_link = 1;
+      break;
+
+    case LTO_LINKER_OUTPUT_DYN: /* .so: PID library */
+      /* On some targets, like i386 it makes sense to build PIC library wihout
+        -fpic for performance reasons.  So no need to adjust flags.  */
+      break;
+
+    case LTO_LINKER_OUTPUT_PIE: /* PIE binary */
+      /* If -fPIC or -fPIE was used at compile time, be sure that
+         flag_pie is 2.  */
+      flag_pie = MAX (flag_pie, flag_pic);
+      flag_pic = 0;
+      break;
+
+    case LTO_LINKER_OUTPUT_EXEC: /* Normal executable */
+      flag_pic = 0;
+      flag_pie = 0;
+      break;
+
+    case LTO_LINKER_OUTPUT_UNKNOWN:
+      break;
+    }
+
   /* Excess precision other than "fast" requires front-end
      support.  */
   flag_excess_precision_cmdline = EXCESS_PRECISION_FAST;
index 6dce5fa4fdb2d9d32148c36cf9d308a3068c05ee..59f21f52c9447ec11582d184b8452591f6b5c84f 100644 (file)
@@ -1,3 +1,10 @@
+2015-11-25  Jan Hubicka  <jh@suse.cz>
+
+       PR lto/67548
+       * lto-plugin.c (linker_output, linker_output_set): New statics.
+       (all_symbols_read_handler): Add -flinker-output option.
+       (onload): Record linker_output info.
+
 2015-07-02  Uros Bizjak  <ubizjak@gmail.com>
 
        * configure.ac: Add AC_USE_SYSTEM_EXTENSIONS.
index 8d957402ba666922c466679c53af2f4b3d46eff7..0a6a767c08deb67a0bbd099cab15d3332757d7b3 100644 (file)
@@ -167,6 +167,8 @@ static unsigned int num_pass_through_items;
 static char debug;
 static char nop;
 static char *resolution_file = NULL;
+static enum ld_plugin_output_file_type linker_output;
+static int linker_output_set;
 
 /* The version of gold being used, or -1 if not gold.  The number is
    MAJOR * 100 + MINOR.  */
@@ -624,8 +626,9 @@ all_symbols_read_handler (void)
 {
   unsigned i;
   unsigned num_lto_args
-    = num_claimed_files + num_offload_files + lto_wrapper_num_args + 1;
+    = num_claimed_files + num_offload_files + lto_wrapper_num_args + 2;
   char **lto_argv;
+  const char *linker_output_str;
   const char **lto_arg_ptr;
   if (num_claimed_files + num_offload_files == 0)
     return LDPS_OK;
@@ -648,6 +651,26 @@ all_symbols_read_handler (void)
   for (i = 0; i < lto_wrapper_num_args; i++)
     *lto_arg_ptr++ = lto_wrapper_argv[i];
 
+  assert (linker_output_set);
+  switch (linker_output)
+    {
+    case LDPO_REL:
+      linker_output_str = "-flinker-output=rel";
+      break;
+    case LDPO_DYN:
+      linker_output_str = "-flinker-output=dyn";
+      break;
+    case LDPO_PIE:
+      linker_output_str = "-flinker-output=pie";
+      break;
+    case LDPO_EXEC:
+      linker_output_str = "-flinker-output=exec";
+      break;
+    default:
+      message (LDPL_FATAL, "unsupported linker output %i", linker_output);
+      break;
+    }
+  *lto_arg_ptr++ = xstrdup (linker_output_str);
   for (i = 0; i < num_claimed_files; i++)
     {
       struct plugin_file_info *info = &claimed_files[i];
@@ -1100,6 +1123,10 @@ onload (struct ld_plugin_tv *tv)
        case LDPT_GOLD_VERSION:
          gold_version = p->tv_u.tv_val;
          break;
+       case LDPT_LINKER_OUTPUT:
+         linker_output = (enum ld_plugin_output_file_type) p->tv_u.tv_val;
+         linker_output_set = 1;
+         break;
        default:
          break;
        }