Richard, I have updated my patch for incremental linking into LTO bytecode, but it now breaks in dwarf2out: lto1: internal compiler error: in dwarf2out_die_ref_for_decl, at dwarf2out.c:5859 0x5d8a37 dwarf2out_die_ref_for_decl ../../gcc/dwarf2out.c:5858 0xa8c311 lto_write_tree_1 ../../gcc/lto-streamer-out.c:423 0xa9539c lto_write_tree ../../gcc/lto-streamer-out.c:449 0xa9539c lto_output_tree_1 ../../gcc/lto-streamer-out.c:483 0xa9539c DFS::DFS(output_block*, tree_node*, bool, bool, bool) ../../gcc/lto-streamer-out.c:670 0xa9656d lto_output_tree(output_block*, tree_node*, bool, bool) ../../gcc/lto-streamer-out.c:1642 0xa8c128 write_global_stream ../../gcc/lto-streamer-out.c:2496 0xa946be lto_output_decl_state_streams(output_block*, lto_out_decl_state*) ../../gcc/lto-streamer-out.c:2543 0xa946be produce_asm_for_decls() ../../gcc/lto-streamer-out.c:2870 0xaf1d3f write_lto ../../gcc/passes.c:2613 0xaf52fe ipa_write_summaries_1 ../../gcc/passes.c:2674 0xaf52fe ipa_write_summaries() ../../gcc/passes.c:2734 0x8052e2 ipa_passes ../../gcc/cgraphunit.c:2470 0x8052e2 symbol_table::compile() ../../gcc/cgraphunit.c:2562 0x7701e7 lto_main() ../../gcc/lto/lto.c:3388
I guess that is early debug info. This happens in quite few testcases with the patch attached. I wonder how we should proceed with this one? * lto-plugin.c: Document options; add -linker-output-known; determine when to use rel and when nolto-rel output. * lto-wrapper.c (run_gcc): Look for -flinker-output=rel also in the list of options passed from the driver. * passes.c (ipa_write_summaries): Only modify statements if body is in memory. * cgrpahunit.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. * 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. * gcc.dg/lto/20081120-2_0.c: Add -flinker-output=nolto-rel * gcc.dg/lto/20090126-1_0.c: Likewise. * gcc.dg/lto/20091020-2_0.c: Likewise. * gcc.dg/lto/20081204-2_0.c: Likewise. * gcc.dg/lto/20091015-1_0.c: Likewise. * gcc.dg/lto/20090126-2_0.c: Likewiwe. * gcc.dg/lto/20090116_0.c: Likewise. * gcc.dg/lto/20081224_0.c: Likewise. * gcc.dg/lto/20091027-1_0.c: Likewise. * gcc.dg/lto/20090219_0.c: Likewise. * gcc.dg/lto/20081212-1_0.c: Likewise. * gcc.dg/lto/20091013-1_0.c: Likewise. * gcc.dg/lto/20081126_0.c: Likewise. * gcc.dg/lto/20090206-1_0.c: Likewise. * gcc.dg/lto/20091016-1_0.c: Likewise. * gcc.dg/lto/20081120-1_0.c: Likewise. * gcc.dg/lto/20091020-1_0.c: Likewise. * gcc.dg/lto/20100426_0.c: Likewise. * gcc.dg/lto/20081204-1_0.c: Likewise. * gcc.dg/lto/20091014-1_0.c: Likewise. * g++.dg/lto/20081109-1_0.C: Likewise. * g++.dg/lto/20100724-1_0.C: Likewise. * g++.dg/lto/20081204-1_0.C: Likewise. * g++.dg/lto/pr45679-2_0.C: Likewise. * g++.dg/lto/20110311-1_0.C: Likewise. * g++.dg/lto/20090302_0.C: Likewise. * g++.dg/lto/20081118_0.C: Likewise. * g++.dg/lto/20091002-2_0.C: Likewise. * g++.dg/lto/20081120-2_0.C: Likewise. * g++.dg/lto/20081123_0.C: Likewise. * g++.dg/lto/20090313_0.C: Likewise. * g++.dg/lto/pr54625-1_0.c: Likewise. * g++.dg/lto/pr48354-1_0.C: Likewise. * g++.dg/lto/20081219_0.C: Likewise. * g++.dg/lto/pr48042_0.C: Likewise. * g++.dg/lto/20101015-2_0.C: Likewise. * g++.dg/lto/pr45679-1_0.C: Likewise. * g++.dg/lto/20091026-1_0.C: Likewise. * g++.dg/lto/pr45621_0.C: Likewise. * g++.dg/lto/20081119-1_0.C: Likewise. * g++.dg/lto/20101010-4_0.C: Likewise. * g++.dg/lto/20081120-1_0.C: Likewise. * g++.dg/lto/20091002-1_0.C: Likewise. * g++.dg/lto/20091002-3_0.C: Likewise. * gfortran.dg/lto/20091016-1_0.f90: Likewise. * gfortran.dg/lto/pr47839_0.f90: Likewise. * gfortran.dg/lto/pr46911_0.f: Likewise. * gfortran.dg/lto/20091028-1_0.f90: Likewise. * gfortran.dg/lto/20091028-2_0.f90: Likewise. Index: gcc/cgraphunit.c =================================================================== --- gcc/cgraphunit.c (revision 259789) +++ gcc/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: gcc/common.opt =================================================================== --- gcc/common.opt (revision 259789) +++ gcc/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: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 259789) +++ gcc/doc/invoke.texi (working copy) @@ -12238,6 +12238,50 @@ object file names should not be used as arguments. @xref{Overall Options}. +@item -flinker-output=@var{type} +@opindex -flinker-output +This option controls the code generation of the link time optimizer. By +default the linker output is determined by the linker plugin automatically. For +debugging the compiler and in the case of incremental linking it may be useful +to control the type manually. + +If @var{type} is @samp{exec} the code generation is configured to produce static +binary. In this case @option{-fpic} and @option{-fpie} are both disabled. + +If @var{type} is @samp{dyn} the code generation is configured to produce shared +library. In this case @option{-fpic} or @option{-fPIC} is preserved. These +options arenot implied to make it possible to build static libraries without +position independent code on architectures this is possible, i.e. on x86. + +If @var{type} is @samp{pie} the code generation is configured to produce +@option{-fpie} executable. This result in similar optimizations as @samp{exec} +except that @option{-fpie} is not disabled if specified at compilation time. + +If @var{type} is @samp{rel} the compiler assumes that incremental linking is +done. The sections containing intermediate code for link-time optimization are +merged, pre-optimized, and output to the resulting object file. In addition if +@option{-ffat-lto-objects} is specified the binary code is produced for future +non-lto linking. The object file produced by incremental linking will be smaller +than a static library produced from the same object files. At link-time the +result of incremental linking will also load faster to compiler than a static +library assuming that majority of objects in the library are used. + +Finally @samp{nolto-rel} configure compiler to for incremental linking where +code generation is forced, final binary is produced and the intermediate code +for later link-time optimization is stripped. When multiple object files are +linked together the resulting code will be optimized better than with link time +optimizations disabled (for example, the cross-module inlining will happen), +most of benefits of whole program optimizations are however lost. + +During the incremental link (by @option{-r}) the linker plugin will default to +@option{rel}. With current interfaces to GNU Binutils it is however not +possible to link incrementally LTO objects and non-LTO objects into a single +mixed object file. In the case any of object files in incremental link can not +be used for link-time optimization the linker plugin will output warning and +use @samp{nolto-rel}. To maintain the whole program optimization it is +recommended to link such objects into static library instead. Alternatively it +is possible to use H.J. Lu's binutils with support for mixed objects. + @item -fuse-ld=bfd @opindex fuse-ld=bfd Use the @command{bfd} linker instead of the default linker. Index: gcc/flag-types.h =================================================================== --- gcc/flag-types.h (revision 259789) +++ gcc/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/gcc.c =================================================================== --- gcc/gcc.c (revision 259789) +++ gcc/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: gcc/lto/lang.opt =================================================================== --- gcc/lto/lang.opt (revision 259789) +++ gcc/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: gcc/lto/lto-lang.c =================================================================== --- gcc/lto/lto-lang.c (revision 259789) +++ gcc/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: gcc/lto-cgraph.c =================================================================== --- gcc/lto-cgraph.c (revision 259789) +++ gcc/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: gcc/lto-wrapper.c =================================================================== --- gcc/lto-wrapper.c (revision 259789) +++ gcc/lto-wrapper.c (working copy) @@ -1054,6 +1054,7 @@ bool have_offload = false; unsigned lto_argc = 0, ltoobj_argc = 0; char **lto_argv, **ltoobj_argv; + bool linker_output_rel = false; bool skip_debug = false; unsigned n_debugobj; @@ -1106,9 +1107,12 @@ file_offset = (off_t) loffset; } fd = open (filename, O_RDONLY | O_BINARY); + /* Linker plugin passes -fresolution and -flinker-output options. */ if (fd == -1) { lto_argv[lto_argc++] = argv[i]; + if (strcmp (argv[i], "-flinker-output=rel") == 0) + linker_output_rel = true; continue; } @@ -1173,6 +1177,11 @@ lto_mode = LTO_MODE_WHOPR; break; + case OPT_flinker_output_: + linker_output_rel = !strcmp (option->arg, "rel"); + break; + + default: break; } @@ -1189,6 +1198,9 @@ fputc ('\n', stderr); } + if (linker_output_rel) + no_partition = true; + if (no_partition) { lto_mode = LTO_MODE_LTO; Index: gcc/passes.c =================================================================== --- gcc/passes.c (revision 259789) +++ gcc/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: gcc/testsuite/g++.dg/lto/20081109-1_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20081109-1_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20081109-1_0.C (working copy) @@ -1,6 +1,6 @@ // { dg-lto-do link } // { dg-require-effective-target fpic } // { dg-lto-options {{-fPIC -flto -flto-partition=1to1}} } -// { dg-extra-ld-options "-fPIC -flto -flto-partition=1to1 -r -nostdlib -fno-exceptions" } +// { dg-extra-ld-options "-fPIC -flto -flto-partition=1to1 -r -nostdlib -fno-exceptions -flinker-output=nolto-rel" } void func(); class Foo { }; void bar() { try { func(); } catch (Foo) { } }; Index: gcc/testsuite/g++.dg/lto/20081118_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20081118_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20081118_0.C (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -r -nostdlib}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ /* We used to ICE because of dangling pointers. */ Index: gcc/testsuite/g++.dg/lto/20081119-1_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20081119-1_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20081119-1_0.C (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -r -nostdlib}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ #include "20081119-1.h" Index: gcc/testsuite/g++.dg/lto/20081120-1_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20081120-1_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20081120-1_0.C (working copy) @@ -1,5 +1,6 @@ // { dg-lto-do link } // { dg-lto-options {{-flto -r -nostdlib}} } +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ extern "C" { extern __inline __attribute__((__gnu_inline__)) int pthread_equal(int, int) Index: gcc/testsuite/g++.dg/lto/20081120-2_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20081120-2_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20081120-2_0.C (working copy) @@ -1,5 +1,6 @@ // { dg-lto-do link } // { dg-lto-options {{-flto -r -nostdlib}} } +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ template < typename > struct Foo { inline void rdstate() { Index: gcc/testsuite/g++.dg/lto/20081123_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20081123_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20081123_0.C (working copy) @@ -1,6 +1,7 @@ // { dg-lto-do link } // { dg-require-effective-target fpic } // { dg-lto-options {{-flto -flto-partition=1to1 -r -nostdlib -fPIC}} } +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ int f(void) Index: gcc/testsuite/g++.dg/lto/20081204-1_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20081204-1_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20081204-1_0.C (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-flto -flto-partition=1to1 -fPIC -r -nostdlib}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ /* Tests for the absence during linking of: lto1: error: type of '_ZTVN10__cxxabiv120__si_class_type_infoE' does Index: gcc/testsuite/g++.dg/lto/20081219_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20081219_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20081219_0.C (working copy) @@ -1,7 +1,7 @@ // { dg-lto-do link } // { dg-require-effective-target fpic } // { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -O2}} } -// { dg-extra-ld-options "-O2 -fPIC -flto -flto-partition=1to1 -r -nostdlib" } +// { dg-extra-ld-options "-O2 -fPIC -flto -flto-partition=1to1 -r -nostdlib -flinker-output=nolto-rel" } typedef long int ptrdiff_t; extern "C" Index: gcc/testsuite/g++.dg/lto/20090302_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20090302_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20090302_0.C (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -r -nostdlib}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ struct Foo { bool Mumble(); static void Bar() { if (foo_->Mumble()) foo_ = 0; } Index: gcc/testsuite/g++.dg/lto/20090313_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20090313_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20090313_0.C (working copy) @@ -1,6 +1,6 @@ // { dg-lto-do link } // { dg-require-effective-target fpic } // { dg-lto-options {{-flto -flto-partition=1to1 -fPIC}} } -// { dg-extra-ld-options "-flto -flto-partition=1to1 -r -nostdlib" } +// { dg-extra-ld-options "-flto -flto-partition=1to1 -r -nostdlib -flinker-output=nolto-rel" } int X; Index: gcc/testsuite/g++.dg/lto/20091002-2_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20091002-2_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20091002-2_0.C (working copy) @@ -1,7 +1,7 @@ // { dg-lto-do link } // { dg-require-effective-target fpic } // { dg-lto-options {{-fPIC}} } -// { dg-extra-ld-options "-fPIC -r -nostdlib" } +// { dg-extra-ld-options "-fPIC -r -nostdlib -flinker-output=nolto-rel" } class DataArray { int max() const { return 0; } Index: gcc/testsuite/g++.dg/lto/20091002-3_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20091002-3_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20091002-3_0.C (working copy) @@ -1,7 +1,7 @@ // { dg-lto-do link } // { dg-require-effective-target fpic } // { dg-lto-options {{-fPIC}} } -// { dg-extra-ld-options "-fPIC -r -nostdlib" } +// { dg-extra-ld-options "-fPIC -r -nostdlib -flinker-output=nolto-rel" } template < class T > class DataArray { Index: gcc/testsuite/g++.dg/lto/20091026-1_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20091026-1_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20091026-1_0.C (working copy) @@ -1,5 +1,5 @@ // { dg-lto-do link } -// { dg-extra-ld-options "-r -nostdlib" } +// { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" } #include "20091026-1_a.h" cObject *cHead::find(const char *objname) const Index: gcc/testsuite/g++.dg/lto/20100724-1_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20100724-1_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20100724-1_0.C (working copy) @@ -1,6 +1,6 @@ /* { dg-lto-do link } */ /* { dg-lto-options {{-ftoplevel-reorder -flto -flto-partition=none} {-ftoplevel-reorder -flto -flto-partition=1to1}} } */ -/* { dg-extra-ld-options {-r -nostdlib} } */ +/* { dg-extra-ld-options {-r -nostdlib -flinker-output=nolto-rel} } */ struct Foo { virtual ~Foo(); }; struct Bar:public Foo { Bar() { } }; Index: gcc/testsuite/g++.dg/lto/20101010-4_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20101010-4_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20101010-4_0.C (working copy) @@ -1,5 +1,6 @@ // { dg-lto-do link } // { dg-lto-options { { -std=c++0x -flto -r -nostdlib } { -std=c++0x -flto -g -r -nostdlib } } } +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ typedef decltype(nullptr) nullptr_t; class shared_ptr { Index: gcc/testsuite/g++.dg/lto/20101015-2_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20101015-2_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20101015-2_0.C (working copy) @@ -1,6 +1,6 @@ // { dg-lto-do link } // { dg-lto-options { { -flto } { -g -flto } } } -// { dg-extra-ld-options "-r -nostdlib" } +// { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" } struct Base { ~Base (); }; void fun(void) { struct Deriv : Base { } x; } Index: gcc/testsuite/g++.dg/lto/20110311-1_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/20110311-1_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/20110311-1_0.C (working copy) @@ -1,5 +1,5 @@ /* { dg-lto-do link } */ -/* { dg-extra-ld-options "-r -nostdlib" } */ +/* { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" } */ struct NullType {}; Index: gcc/testsuite/g++.dg/lto/pr45621_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/pr45621_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/pr45621_0.C (working copy) @@ -1,5 +1,5 @@ // { dg-lto-do assemble } -// { dg-extra-ld-options "-O2 -fipa-cp-clone -flto -nostdlib -r" } +// { dg-extra-ld-options "-O2 -fipa-cp-clone -flto -nostdlib -r -flinker-output=nolto-rel" } #include "pr45621.h" void Index: gcc/testsuite/g++.dg/lto/pr48042_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/pr48042_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/pr48042_0.C (working copy) @@ -1,5 +1,5 @@ // { dg-lto-do link } -// { dg-extra-ld-options "-r -nostdlib -g" } +// { dg-extra-ld-options "-r -nostdlib -g -flinker-output=nolto-rel" } class A { virtual int x() = 0; Index: gcc/testsuite/g++.dg/lto/pr48354-1_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/pr48354-1_0.C (revision 259789) +++ gcc/testsuite/g++.dg/lto/pr48354-1_0.C (working copy) @@ -1,6 +1,6 @@ // { dg-lto-do link } // { dg-lto-options { { -g -flto } } } -// { dg-extra-ld-options "-r -nostdlib" } +// { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" } template<typename T> struct Identity { typedef T type; }; struct S { Index: gcc/testsuite/g++.dg/lto/pr54625-1_0.c =================================================================== --- gcc/testsuite/g++.dg/lto/pr54625-1_0.c (revision 259789) +++ gcc/testsuite/g++.dg/lto/pr54625-1_0.c (working copy) @@ -1,5 +1,5 @@ /* { dg-lto-do link } */ -/* { dg-extra-ld-options { -r -nostdlib } } */ +/* { dg-extra-ld-options { -r -nostdlib -flinker-output=nolto-rel } } */ float a; double sin (); Index: gcc/testsuite/gcc.dg/lto/20081120-1_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20081120-1_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20081120-1_0.c (working copy) @@ -1,5 +1,6 @@ /* { dg-lto-do link } */ /* { dg-lto-options {{-flto -r -nostdlib}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ extern int stat(void) __asm__("" "stat64"); extern inline int stat(void) { } static void foo(void) { stat(); } Index: gcc/testsuite/gcc.dg/lto/20081120-2_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20081120-2_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20081120-2_0.c (working copy) @@ -1,3 +1,4 @@ /* { dg-lto-do link } */ /* { dg-lto-options {{-flto -flto-partition=1to1 -r -nostdlib}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ void bar(void) {} Index: gcc/testsuite/gcc.dg/lto/20081126_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20081126_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20081126_0.c (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } } */ /* { dg-lto-options {{-flto -r -nostdlib}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ int f(void) { register int ri asm("edi"); Index: gcc/testsuite/gcc.dg/lto/20081204-1_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20081204-1_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20081204-1_0.c (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-flto -flto-partition=1to1 -fPIC -r -nostdlib}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ /* Tests for the absence during linking of: lto1: error: type of 'i' does not match original declaration */ Index: gcc/testsuite/gcc.dg/lto/20081204-2_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20081204-2_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20081204-2_0.c (working copy) @@ -1,5 +1,6 @@ /* { dg-lto-do link } */ /* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } } */ /* { dg-lto-options {{-w -flto -fPIC -r -nostdlib}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ register int ri asm("edi"); Index: gcc/testsuite/gcc.dg/lto/20081212-1_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20081212-1_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20081212-1_0.c (working copy) @@ -1,4 +1,5 @@ /* { dg-lto-do link } */ /* { dg-lto-options {{-r -nostdlib}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ int exported_var = 42; /* { dg-final { scan-symbol "exported_var" } } */ Index: gcc/testsuite/gcc.dg/lto/20081224_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20081224_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20081224_0.c (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-flto -flto-partition=1to1 -r -nostdlib -fPIC}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ #include "20081224_0.h" extern struct foo x; Index: gcc/testsuite/gcc.dg/lto/20090116_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20090116_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20090116_0.c (working copy) @@ -1,7 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-O1 -flto -flto-partition=1to1 -fPIC}} } */ -/* { dg-extra-ld-options {-r -nostdlib -O0} } */ +/* { dg-extra-ld-options {-r -nostdlib -O0 -flinker-output=nolto-rel} } */ int foo(void) { int ret, i; Index: gcc/testsuite/gcc.dg/lto/20090126-1_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20090126-1_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20090126-1_0.c (working copy) @@ -1,6 +1,6 @@ /* { dg-lto-do link } */ /* { dg-lto-options {{-O0 -flto -flto-partition=1to1}} } */ -/* { dg-extra-ld-options {-r -nostdlib -O2 -flto -flto-partition=1to1} } */ +/* { dg-extra-ld-options {-r -nostdlib -O2 -flto -flto-partition=1to1 -flinker-output=nolto-rel} } */ int main(int argc, char **argv) { return 0; Index: gcc/testsuite/gcc.dg/lto/20090126-2_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20090126-2_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20090126-2_0.c (working copy) @@ -1,7 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-fPIC -O2 -flto -flto-partition=1to1}} } */ -/* { dg-extra-ld-options {-fno-PIC -r -nostdlib -O2 -flto -flto-partition=1to1} } */ +/* { dg-extra-ld-options {-fno-PIC -r -nostdlib -O2 -flto -flto-partition=1to1 -flinker-output=nolto-rel} } */ int main(int argc, char **argv) { return 0; Index: gcc/testsuite/gcc.dg/lto/20090206-1_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20090206-1_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20090206-1_0.c (working copy) @@ -3,6 +3,7 @@ /* { dg-lto-options {{-fPIC -r -nostdlib -flto -flto-partition=1to1 -msse2}} } */ /* { dg-require-effective-target sse2 } */ /* { dg-suppress-ld-options {-fPIC -msse2} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ typedef short v8hi __attribute__((__vector_size__(16))); void func (void) { Index: gcc/testsuite/gcc.dg/lto/20090219_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20090219_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20090219_0.c (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-O3 -flto -flto-partition=1to1 -fPIC -r -nostdlib}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ struct Foo { int f1, f2, f3, f4, f5; }; Index: gcc/testsuite/gcc.dg/lto/20091013-1_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20091013-1_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20091013-1_0.c (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-fPIC -r -nostdlib -flto} {-fPIC -r -nostdlib -O2 -flto}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ void * HeapAlloc(void*,unsigned int,unsigned long); Index: gcc/testsuite/gcc.dg/lto/20091014-1_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20091014-1_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20091014-1_0.c (working copy) @@ -1,5 +1,6 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-fPIC -r -nostdlib -flto}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ /* Empty file. See PR41173. */ Index: gcc/testsuite/gcc.dg/lto/20091015-1_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20091015-1_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20091015-1_0.c (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-fPIC -r -nostdlib -O2 -flto} {-fPIC -r -nostdlib -O2 -flto -flto-partition=1to1}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ #include "20091015-1_b.h" void diagnostic_initialize (FILE **stream) { *stream = stderr; } Index: gcc/testsuite/gcc.dg/lto/20091016-1_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20091016-1_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20091016-1_0.c (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-fPIC -r -nostdlib -O2 -flto}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ typedef struct VEC_constructor_elt_gc { } VEC_constructor_elt_gc; #include "20091016-1_a.h" Index: gcc/testsuite/gcc.dg/lto/20091020-1_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20091020-1_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20091020-1_0.c (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-fPIC -r -nostdlib -flto}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ typedef struct { int NumPackStreams; Index: gcc/testsuite/gcc.dg/lto/20091020-2_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20091020-2_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20091020-2_0.c (working copy) @@ -1,6 +1,7 @@ /* { dg-lto-do link } */ /* { dg-require-effective-target fpic } */ /* { dg-lto-options {{-fPIC -r -nostdlib -flto}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ typedef struct { int NumPackStreams; Index: gcc/testsuite/gcc.dg/lto/20091027-1_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20091027-1_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20091027-1_0.c (working copy) @@ -1,5 +1,5 @@ /* { dg-lto-do link } */ -/* { dg-extra-ld-options "-r -nostdlib" } */ +/* { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" } */ typedef struct _xmlDict xmlDict; struct _xmlDict { Index: gcc/testsuite/gcc.dg/lto/20100426_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/20100426_0.c (revision 259789) +++ gcc/testsuite/gcc.dg/lto/20100426_0.c (working copy) @@ -1,5 +1,6 @@ /* { dg-lto-do link } */ /* { dg-lto-options {{-r -nostdlib -flto -g}} } */ +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */ long Perl_my_htonl (long l) { Index: gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90 =================================================================== --- gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90 (revision 259789) +++ gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90 (working copy) @@ -1,5 +1,6 @@ ! { dg-lto-do link } ! { dg-lto-options {{-flto -g -fPIC -r -nostdlib} {-O -flto -g -fPIC -r -nostdlib}} } +! { dg-extra-ld-options "-flinker-output=nolto-rel" } FUNCTION makenumberstring(x) IMPLICIT NONE Index: gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90 =================================================================== --- gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90 (revision 259789) +++ gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90 (working copy) @@ -1,5 +1,5 @@ ! { dg-lto-do link } -! { dg-extra-ld-options "-r -nostdlib -finline-functions" } +! { dg-extra-ld-options "-r -nostdlib -finline-functions -flinker-output=nolto-rel" } SUBROUTINE int_gen_ti_header_char( hdrbuf, hdrbufsize, itypesize, & DataHandle, Element, VarName, Data, code ) Index: gcc/testsuite/gfortran.dg/lto/20091028-2_0.f90 =================================================================== --- gcc/testsuite/gfortran.dg/lto/20091028-2_0.f90 (revision 259789) +++ gcc/testsuite/gfortran.dg/lto/20091028-2_0.f90 (working copy) @@ -1,5 +1,5 @@ ! { dg-lto-do link } -! { dg-extra-ld-options "-r -nostdlib -finline-functions" } +! { dg-extra-ld-options "-r -nostdlib -finline-functions -flinker-output=nolto-rel" } SUBROUTINE int_gen_ti_header_char( hdrbuf, hdrbufsize, itypesize, & DataHandle, Element, VarName, Data, code ) Index: gcc/testsuite/gfortran.dg/lto/pr46911_0.f =================================================================== --- gcc/testsuite/gfortran.dg/lto/pr46911_0.f (revision 259789) +++ gcc/testsuite/gfortran.dg/lto/pr46911_0.f (working copy) @@ -1,6 +1,6 @@ ! { dg-lto-do link } ! { dg-lto-options {{ -O2 -flto -g }} } -! { dg-extra-ld-options "-r -nostdlib" } +! { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" } common/main1/ eps(2) call dalie6s(iqmod6,1,wx,cor6d) end Index: gcc/testsuite/gfortran.dg/lto/pr47839_0.f90 =================================================================== --- gcc/testsuite/gfortran.dg/lto/pr47839_0.f90 (revision 259789) +++ gcc/testsuite/gfortran.dg/lto/pr47839_0.f90 (working copy) @@ -1,6 +1,6 @@ ! { dg-lto-do link } ! { dg-lto-options {{ -g -flto }} } -! { dg-extra-ld-options "-r -nostdlib" } +! { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" } MODULE globalvar_mod integer :: xstop Index: gcc/toplev.c =================================================================== --- gcc/toplev.c (revision 259789) +++ gcc/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) Index: lto-plugin/lto-plugin.c =================================================================== --- lto-plugin/lto-plugin.c (revision 259789) +++ lto-plugin/lto-plugin.c (working copy) @@ -27,10 +27,13 @@ More information at http://gcc.gnu.org/wiki/whopr/driver. This plugin should be passed the lto-wrapper options and will forward them. - It also has 2 options of its own: + It also has options at his own: -debug: Print the command line used to run lto-wrapper. -nop: Instead of running lto-wrapper, pass the original to the plugin. This - only works if the input files are hybrid. */ + only works if the input files are hybrid. + -linker-output-known: Do not determine linker output + -sym-style={none,win32,underscore|uscore} + -pass-through */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -159,6 +162,7 @@ static struct plugin_file_info *claimed_files = NULL; static unsigned int num_claimed_files = 0; +static unsigned int non_claimed_files = 0; /* List of files with offloading. */ static struct plugin_offload_file *offload_files; @@ -185,6 +189,7 @@ static char *resolution_file = NULL; static enum ld_plugin_output_file_type linker_output; static int linker_output_set; +static int linker_output_known; /* The version of gold being used, or -1 if not gold. The number is MAJOR * 100 + MINOR. */ @@ -637,7 +642,8 @@ all_symbols_read_handler (void) { unsigned i; - unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 3; + unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 2 + + !linker_output_known; char **lto_argv; const char *linker_output_str = NULL; const char **lto_arg_ptr; @@ -661,26 +667,37 @@ for (i = 0; i < lto_wrapper_num_args; i++) *lto_arg_ptr++ = lto_wrapper_argv[i]; - assert (linker_output_set); - switch (linker_output) + if (!linker_output_known) { - 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; + assert (linker_output_set); + switch (linker_output) + { + case LDPO_REL: + if (non_claimed_files) + { + message (LDPL_WARNING, "incremental linking of LTO and non-LTO " + "objects; using -flinker-output=nolto-rel which will " + "bypass whole program optimization"); + linker_output_str = "-flinker-output=nolto-rel"; + } + else + 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); } - *lto_arg_ptr++ = xstrdup (linker_output_str); if (num_offload_files > 0) { @@ -1108,6 +1125,7 @@ goto cleanup; err: + non_claimed_files++; free (lto_file.name); cleanup: @@ -1122,6 +1140,8 @@ static void process_option (const char *option) { + if (strcmp (option, "-linker-output-known") == 0) + linker_output_known = 1; if (strcmp (option, "-debug") == 0) debug = 1; else if (strcmp (option, "-nop") == 0)