Hi,
this patch adds the symtab support for LTO incremental linking. Most of the
code path is same for both modes of incremental link except hat we want to
produce LTO object file rather than compile down to assembly.

Only non-obvious changes are in ipa.c where I hit a bug where we stream in 
initializers that are going to be eliminated form the symbol table for no
good reasons.

Bootstrapped/regtested x86_64-linux with rest of the incremental link patchset.

Honza

        * passes.c (ipa_write_summaries): Only modify statements if body
        is in memory.
        * cgraphunit.c (ipa_passes): Also produce intermeidate code when
        incrementally linking.
        (ipa_passes): Likewise.
        * lto-cgraph.c (lto_output_node): When incrementally linking do not
        pass down resolution info.
        * common.opt (flag_incremental_link): Update info.
        * gcc.c (plugin specs): Turn flinker-output=* to
        -plugin-opt=-linker-output-known
        * toplev.c (compile_file): Also cut compilation when doing incremental
        link.
        * flag-types. (enum lto_partition_model): Add
        LTO_LINKER_OUTPUT_NOLTOREL.
        (invoke.texi): Add -flinker-output docs.
        * ipa.c (symbol_table::remove_unreachable_nodes): Handle LTO incremental
        link same way as WPA; do not stream in dead initializers.

        * lang.opt (lto_linker_output): Add nolto-rel.
        * lto-lang.c (lto_post_options): Handle LTO_LINKER_OUTPUT_REL
        and LTO_LINKER_OUTPUT_NOLTOREL.
        (lto_init): Generate lto when doing incremental link.
        * lto.c (lto_precess_name): Add lto1-inclink.
Index: cgraphunit.c
===================================================================
--- cgraphunit.c        (revision 260042)
+++ cgraphunit.c        (working copy)
@@ -2452,8 +2452,10 @@
   if (flag_generate_lto || flag_generate_offload)
     targetm.asm_out.lto_start ();
 
-  if (!in_lto_p)
+  if (!in_lto_p || flag_incremental_link == 2)
     {
+      if (!quiet_flag)
+       fprintf (stderr, "Streaming LTO\n");
       if (g->have_offload)
        {
          section_name_prefix = OFFLOAD_SECTION_NAME_PREFIX;
@@ -2472,7 +2474,9 @@
   if (flag_generate_lto || flag_generate_offload)
     targetm.asm_out.lto_end ();
 
-  if (!flag_ltrans && (in_lto_p || !flag_lto || flag_fat_lto_objects))
+  if (!flag_ltrans
+      && ((in_lto_p && flag_incremental_link != 2)
+         || !flag_lto || flag_fat_lto_objects))
     execute_ipa_pass_list (passes->all_regular_ipa_passes);
   invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
 
@@ -2559,7 +2563,8 @@
 
   /* Do nothing else if any IPA pass found errors or if we are just streaming 
LTO.  */
   if (seen_error ()
-      || (!in_lto_p && flag_lto && !flag_fat_lto_objects))
+      || ((!in_lto_p || flag_incremental_link == 2)
+         && flag_lto && !flag_fat_lto_objects))
     {
       timevar_pop (TV_CGRAPHOPT);
       return;
Index: common.opt
===================================================================
--- common.opt  (revision 260042)
+++ common.opt  (working copy)
@@ -48,7 +48,8 @@
 
 ; 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).
+; can still be bound) and 2 indicates that the IL is going to be linked and
+; and output to LTO object file.
 Variable
 int flag_incremental_link = 0
 
Index: flag-types.h
===================================================================
--- flag-types.h        (revision 260042)
+++ flag-types.h        (working copy)
@@ -289,6 +289,7 @@
 enum lto_linker_output {
   LTO_LINKER_OUTPUT_UNKNOWN,
   LTO_LINKER_OUTPUT_REL,
+  LTO_LINKER_OUTPUT_NOLTOREL,
   LTO_LINKER_OUTPUT_DYN,
   LTO_LINKER_OUTPUT_PIE,
   LTO_LINKER_OUTPUT_EXEC
Index: gcc.c
===================================================================
--- gcc.c       (revision 260042)
+++ gcc.c       (working copy)
@@ -961,6 +961,7 @@
     -plugin %(linker_plugin_file) \
     -plugin-opt=%(lto_wrapper) \
     -plugin-opt=-fresolution=%u.res \
+    %{flinker-output=*:-plugin-opt=-linker-output-known} \
     %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} 
\
     }" PLUGIN_COND_CLOSE
 #else
Index: ipa.c
===================================================================
--- ipa.c       (revision 260042)
+++ ipa.c       (working copy)
@@ -130,9 +130,9 @@
                     constant folding.  Keep references alive so partitioning
                     knows about potential references.  */
                  || (VAR_P (node->decl)
-                     && flag_wpa
-                     && ctor_for_folding (node->decl)
-                        != error_mark_node))))
+                     && (flag_wpa || flag_incremental_link == 2)
+                     && dyn_cast <varpool_node *> (node)
+                          ->ctor_useable_for_folding_p ()))))
        {
          /* Be sure that we will not optimize out alias target
             body.  */
@@ -622,7 +622,7 @@
            fprintf (file, " %s", vnode->dump_name ());
           vnext = next_variable (vnode);
          /* Signal removal to the debug machinery.  */
-         if (! flag_wpa)
+         if (! flag_wpa || flag_incremental_link == 2)
            {
              vnode->definition = false;
              (*debug_hooks->late_global_decl) (vnode->decl);
@@ -640,8 +640,9 @@
              changed = true;
            }
          /* Keep body if it may be useful for constant folding.  */
-         if ((init = ctor_for_folding (vnode->decl)) == error_mark_node
-             && !POINTER_BOUNDS_P (vnode->decl))
+         if ((flag_wpa || flag_incremental_link == 2)
+             || ((init = ctor_for_folding (vnode->decl)) == error_mark_node
+                 && !POINTER_BOUNDS_P (vnode->decl)))
            vnode->remove_initializer ();
          else
            DECL_INITIAL (vnode->decl) = init;
Index: lto/lang.opt
===================================================================
--- lto/lang.opt        (revision 260042)
+++ lto/lang.opt        (working copy)
@@ -34,6 +34,9 @@
 Enum(lto_linker_output) String(rel) Value(LTO_LINKER_OUTPUT_REL)
 
 EnumValue
+Enum(lto_linker_output) String(nolto-rel) Value(LTO_LINKER_OUTPUT_NOLTOREL)
+
+EnumValue
 Enum(lto_linker_output) String(dyn) Value(LTO_LINKER_OUTPUT_DYN)
 
 EnumValue
Index: lto/lto-lang.c
===================================================================
--- lto/lto-lang.c      (revision 260042)
+++ lto/lto-lang.c      (working copy)
@@ -879,7 +879,27 @@
   switch (flag_lto_linker_output)
     {
     case LTO_LINKER_OUTPUT_REL: /* .o: incremental link producing LTO IL  */
+      /* Configure compiler same way as normal frontend would do with -flto:
+        this way we read the trees (declarations & types), symbol table,
+        optimization summaries and link them. Subsequently we output new LTO
+        file.  */
+      flag_lto = "";
+      flag_incremental_link = 2;
       flag_whole_program = 0;
+      flag_wpa = 0;
+      flag_generate_lto = 1;
+      /* It would be cool to produce .o file directly, but our current
+        simple objects does not contain the lto symbol markers.  Go the slow
+        way through the asm file.  */
+      lang_hooks.lto.begin_section = lhd_begin_section;
+      lang_hooks.lto.append_data = lhd_append_data;
+      lang_hooks.lto.end_section = lhd_end_section;
+      if (flag_ltrans)
+       error ("-flinker-output=rel and -fltrans are mutually exclussive");
+      break;
+
+    case LTO_LINKER_OUTPUT_NOLTOREL: /* .o: incremental link producing asm  */
+      flag_whole_program = 0;
       flag_incremental_link = 1;
       break;
 
@@ -1269,7 +1289,7 @@
   in_lto_p = true;
 
   /* We need to generate LTO if running in WPA mode.  */
-  flag_generate_lto = (flag_wpa != NULL);
+  flag_generate_lto = (flag_incremental_link == 2 || flag_wpa != NULL);
 
   /* Create the basic integer types.  */
   build_common_tree_nodes (flag_signed_char);
Index: lto/lto.c
===================================================================
--- lto/lto.c   (revision 260042)
+++ lto/lto.c   (working copy)
@@ -3257,7 +3257,7 @@
 lto_process_name (void)
 {
   if (flag_lto)
-    setproctitle ("lto1-lto");
+    setproctitle (flag_incremental_link == 2 ? "lto1-inclink" : "lto1-lto");
   if (flag_wpa)
     setproctitle ("lto1-wpa");
   if (flag_ltrans)
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c        (revision 260042)
+++ lto-cgraph.c        (working copy)
@@ -540,7 +540,10 @@
   bp_pack_value (&bp, node->thunk.thunk_p, 1);
   bp_pack_value (&bp, node->parallelized_function, 1);
   bp_pack_enum (&bp, ld_plugin_symbol_resolution,
-               LDPR_NUM_KNOWN, node->resolution);
+               LDPR_NUM_KNOWN,
+               /* When doing incremental link, we will get new resolution
+                  info next time we process the file.  */
+               flag_incremental_link ? LDPR_UNKNOWN : node->resolution);
   bp_pack_value (&bp, node->instrumentation_clone, 1);
   bp_pack_value (&bp, node->split_part, 1);
   streamer_write_bitpack (&bp);
Index: lto-streamer-out.c
===================================================================
--- lto-streamer-out.c  (revision 260042)
+++ lto-streamer-out.c  (working copy)
@@ -2406,7 +2406,8 @@
                }
              decl_state = lto_new_out_decl_state ();
              lto_push_out_decl_state (decl_state);
-             if (gimple_has_body_p (node->decl) || !flag_wpa
+             if (gimple_has_body_p (node->decl)
+                 || (!flag_wpa && flag_incremental_link != 2)
                  /* Thunks have no body but they may be synthetized
                     at WPA time.  */
                  || DECL_ARGUMENTS (node->decl))
@@ -2438,7 +2439,7 @@
              decl_state = lto_new_out_decl_state ();
              lto_push_out_decl_state (decl_state);
              if (DECL_INITIAL (node->decl) != error_mark_node
-                 || !flag_wpa)
+                 || (!flag_wpa && flag_incremental_link != 2))
                output_constructor (node);
              else
                copy_function_or_variable (node);
Index: passes.c
===================================================================
--- passes.c    (revision 260042)
+++ passes.c    (working copy)
@@ -2708,7 +2708,7 @@
     {
       struct cgraph_node *node = order[i];
 
-      if (node->has_gimple_body_p ())
+      if (gimple_has_body_p (node->decl))
        {
          /* When streaming out references to statements as part of some IPA
             pass summary, the statements need to have uids assigned and the
Index: toplev.c
===================================================================
--- toplev.c    (revision 260042)
+++ toplev.c    (working copy)
@@ -495,7 +495,8 @@
 
   /* Compilation unit is finalized.  When producing non-fat LTO object, we are
      basically finished.  */
-  if (in_lto_p || !flag_lto || flag_fat_lto_objects)
+  if ((in_lto_p && flag_incremental_link != 2)
+      || !flag_lto || flag_fat_lto_objects)
     {
       /* File-scope initialization for AddressSanitizer.  */
       if (flag_sanitize & SANITIZE_ADDRESS)

Reply via email to