[lto] Support mixed EH settings

Andrew Thomas Pinski pinskia@gmail.com
Mon Nov 10 01:22:00 GMT 2008



Sent from my iPhone

On Nov 9, 2008, at 3:21 PM, Diego Novillo <dnovillo@google.com> wrote:

> This patch adds support for mixed EH settings during
> analysis.  Instead of forcing EH to be set, the compiler will now
> wait unitl a file with an EH table is read-in.  If that happens,
> the EH machinery is initialized.
>
> The only issue not addressed by this patch is the choice of EH
> personality.  We blindly set it to gxx_personality, which is less
> than ideal.  In general, we could either mark EH tables with
> their personality during LGEN and then use a super-set of all the
> personalities found.  I think that when mixing C and C++, using
> gxx_personality is fine, but I'm not quite sure what would happen
> with other languages (or even if it's a problem altogether).

Oh it is definetly a problem. Consider obective-c code that catches an  
exception, it will no longer work correctly as it will no longer be  
able to match the exception.

Thanks,
Andrew Pinsky

>
>
> I also added support for using different flags during linking, so
> that we can test this case:
>
> $ g++ -fwhopr -c file-with-eh.cc
> $ g++ -fwhopr -fno-exceptions file-with-eh.o
>
> which was causing an ICE during WPA.  The new dg- command is
> dg-extra-ld-options.
>
> Tested on x86_64.
>
>
> Diego.
>
>
>    * lto-function-in.c: Include libfuncs.h.
>    (lto_eh_runtime_type): Move from lto/lto-lang.c
>    (lto_init_eh): Likewise.
>    Set flag_exceptions and call init_eh.
>    (input_eh_regions): Call lto_init_eh once if an EH table
>    is found.
>    * Makefile.in (lto-function-in.o): Add dependency on
>    libfuncs.h.
>
> lto/ChangeLog
>
>    * lto/lto.c (lto_fixup_tree): Change error message locus
>    information to include location of mismatching
>    declaration.
>    Use TREE_NO_WARNING to avoid repeated messages.
>    (lto_main): If lto_fixup_decls emitted any errors, exit.
>    * lto/lto-lang.c: Don't include libfuncs.h and except.h
>    (lto_init_options): Don't enable exceptions by default.
>    (lto_eh_runtime_type): Move to lto-function-in.c
>    (lto_init_eh): Likewise.
>    (lto_init): Don't call lto_init_eh.
>    * lto/Make-lang.in (lto-lang.o): Remove dependency on
>    libfuncs.h and except.h.
>
> testsuite/ChangeLog.lto
>
>    * g++.dg/lto/20081109-1_0.C: New.
>    * g++.dg/lto/20081109_0.C: New.
>    * g++.dg/lto/20081109_1.C: New.
>    * lib/lto.exp (lto-get-options-main): Add support for
>    adding extra flags to the link stage with
>    dg-extra-ld-options.
>    (lto-execute): Use dg-extra-ld-options when calling
>    lto-link-and-maybe-run.
>
> Index: lto-function-in.c
> ===================================================================
> --- lto-function-in.c    (revision 141708)
> +++ lto-function-in.c    (working copy)
> @@ -42,6 +42,7 @@ Boston, MA 02110-1301, USA.  */
> #include "function.h"
> #include "ggc.h"
> #include "diagnostic.h"
> +#include "libfuncs.h"
> #include "except.h"
> #include "debug.h"
> #include "vec.h"
> @@ -1757,6 +1758,41 @@ fixup_eh_region_pointers (struct functio
> }
>
>
> +/* Return the runtime type for type T.  For LTO, we assume that each
> +   front end has generated the appropriate runtime types (see
> +   output_eh_region), so there is nothing for us to do here.  */
> +
> +static tree
> +lto_eh_runtime_type (tree t)
> +{
> +  return t;
> +}
> +
> +
> +/* Initialize EH support.  */
> +
> +static void
> +lto_init_eh (void)
> +{
> +  /* Contrary to most other FEs, we only initialize EH support when  
> at
> +     least one of the files in the set contains exception regions in
> +     it.  Since this happens much later than the call to init_eh in
> +     lang_dependent_init, we have to set flag_exceptions and call
> +     init_eh again to initialize the EH tables.  */
> +  flag_exceptions = 1;
> +  init_eh ();
> +
> +  /* FIXME lto.  Use g++'s personality for now, but this should be
> +     derived from either the input files or some global flag.  It's
> +     not clear yet what should happen when languages other than C or
> +     C++ are in the mix.  */
> +  eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
> +                         ? "__gxx_personality_sj0"
> +                         : "__gxx_personality_v0");
> +  default_init_unwind_resume_libfunc ();
> +  lang_eh_runtime_type = lto_eh_runtime_type;
> +}
> +
>
> /* Read the exception table for FN from IB using the data descriptors
>    in DATA_IN.  */
> @@ -1771,6 +1807,17 @@ input_eh_regions (struct lto_input_block
>   tag = input_record_start (ib);
>   if (tag == LTO_eh_table)
>     {
> +      static bool eh_initialized_p = false;
> +
> +      /* If the file contains EH regions, then it was compiled with
> +     -fexceptions.  In that case, initialize the backend EH
> +     machinery.  */
> +      if (!eh_initialized_p)
> +    {
> +      lto_init_eh ();
> +      eh_initialized_p = true;
> +    }
> +
>       gcc_assert (fn->eh);
>
>       last_region = lto_input_sleb128 (ib);
> Index: testsuite/g++.dg/lto/20081109-1_0.C
> ===================================================================
> --- testsuite/g++.dg/lto/20081109-1_0.C    (revision 0)
> +++ testsuite/g++.dg/lto/20081109-1_0.C    (revision 0)
> @@ -0,0 +1,7 @@
> +// { dg-do link }
> +// { dg-options "{-fPIC -fwhopr}" }
> +// { dg-extra-ld-options "-fPIC -fwhopr -shared -fno-exceptions" }
> +void func(); class Foo { };
> +void bar() { try { func(); } catch (Foo) { } };
> +//void func() {}
> +//main() {}
> Index: testsuite/g++.dg/lto/20081109_0.C
> ===================================================================
> --- testsuite/g++.dg/lto/20081109_0.C    (revision 0)
> +++ testsuite/g++.dg/lto/20081109_0.C    (revision 0)
> @@ -0,0 +1,28 @@
> +extern "C" { void abort (void);}
> +int foo (int);
> +
> +class A
> +{
> +  int x;
> +
> +public:
> +  A() { x = 2304; }
> +  ~A() { if (x != 2305) abort (); }
> +  void inc () { x++; }
> +};
> +
> +
> +int main()
> +{
> +  A x;
> +  x.inc();
> +  try
> +    {
> +      foo (0);
> +      abort ();    // Should not execute
> +    }
> +  catch (int e)
> +    {
> +      return 0;
> +    }
> +}
> Index: testsuite/g++.dg/lto/20081109_1.C
> ===================================================================
> --- testsuite/g++.dg/lto/20081109_1.C    (revision 0)
> +++ testsuite/g++.dg/lto/20081109_1.C    (revision 0)
> @@ -0,0 +1,4 @@
> +int foo (int x)
> +{
> +  throw 10;
> +}
> Index: testsuite/lib/lto.exp
> ===================================================================
> --- testsuite/lib/lto.exp    (revision 141708)
> +++ testsuite/lib/lto.exp    (working copy)
> @@ -146,6 +146,9 @@ proc lto-link-and-maybe-run { testname o
> # SRC is the full pathname of the primary source file.
> proc lto-get-options-main { src } {
>     global compile_type
> +    global dg-extra-ld-options
> +
> +    set dg-extra-ld-options ""
>
>     # dg-options sets a variable called dg-extra-tool-flags.
>     set dg-extra-tool-flags ""
> @@ -156,14 +159,14 @@ proc lto-get-options-main { src } {
>     # dg-require-* sets dg-do-what.
>     upvar dg-do-what dg-do-what
>
> -    verbose "getting options for $src"
>     set tmp [dg-get-options $src]
> +    verbose "getting options for $src: $tmp"
>     foreach op $tmp {
>    set cmd [lindex $op 0]
>    verbose "cmd is $cmd"
>    if { ![string compare "dg-options" $cmd] \
>         || [string match "dg-skip-if" $cmd] \
> -         || [string match "dg-require-*" $cmd]  } {
> +         || [string match "dg-require-*" $cmd] } {
>        set status [catch "$op" errmsg]
>        if { $status != 0 } {
>        perror "src: $errmsg for \"$op\"\n"
> @@ -184,6 +187,9 @@ proc lto-get-options-main { src } {
>        } else {
>        warning "lto.exp does not support dg-do $dgdo"
>        }
> +    } elseif { ![string compare "dg-extra-ld-options" $cmd] } {
> +        set dg-extra-ld-options [lindex $op 2]
> +        verbose "dg-extra-ld-options for main is ${dg-extra-ld- 
> options}"
>    } else {
>        # Ignore unrecognized dg- commands, but warn about them.
>        warning "lto.exp does not support $cmd"
> @@ -192,6 +198,7 @@ proc lto-get-options-main { src } {
>
>     # Return flags to use for compiling the primary source file and  
> for
>     # linking.
> +    verbose "dg-extra-tool-flags for main is ${dg-extra-tool-flags}"
>     return ${dg-extra-tool-flags}
> }
>
> @@ -250,6 +257,7 @@ proc lto-execute { src1 sid } {
>     global compiler_conditional_xfail_data
>     global dg-do-what-default
>     global compile_type
> +    global dg-extra-ld-options
>
>     # Get extra flags for this test from the primary source file, and
>     # process other dg-* options that this suite supports.  Warn about
> @@ -362,7 +370,7 @@ proc lto-execute { src1 sid } {
>         || ![string compare "link" $compile_type] } {
>        lto-link-and-maybe-run \
>            "[lindex $obj_list 0]-[lindex $obj_list end]" \
> -            $obj_list $execname $option $extra_flags(0) $option
> +            $obj_list $execname $option ${dg-extra-ld-options}  
> $option
>    }
>
>    # Clean up object files.
> Index: lto/lto.c
> ===================================================================
> --- lto/lto.c    (revision 141708)
> +++ lto/lto.c    (working copy)
> @@ -25,6 +25,7 @@ Boston, MA 02110-1301, USA.  */
> #include "opts.h"
> #include "toplev.h"
> #include "tree.h"
> +#include "diagnostic.h"
> #include "tm.h"
> #include "libiberty.h"
> #include "cgraph.h"
> @@ -794,13 +795,30 @@ lto_fixup_tree (tree *tp, int *walk_subt
>       if (t != prevailing)
>    {
>      if (TREE_CODE (t) == FUNCTION_DECL
> -          && flag_exceptions
>          && TREE_NOTHROW (prevailing) != TREE_NOTHROW (t))
>        {
> +          /* If the prevailing definition does not throw but the
> +         declaration (T) was considered throwing, then we
> +         simply add PREVAILING to the list of throwing
> +         functions.  However, if the opposite is true, then
> +         the call to PREVAILING was generated assuming that
> +         the function didn't throw, which means that CFG
> +         cleanup may have removed surrounding try/catch
> +         regions.  In that case, emit an error.
> +
> +         Note that we currently accept these cases even when
> +         they occur within a single file.  It's certainly a
> +         user error, but we silently allow the compiler to
> +         remove surrounding try/catch regions.  Perhaps we
> +         could demote this to a warning instead.  */
>          if (TREE_NOTHROW (prevailing))
>        lto_mark_nothrow_fndecl (prevailing);
> -          else
> -        error ("%qD change to exception throwing", prevailing);
> +          else if (!TREE_NO_WARNING (prevailing))
> +        {
> +          error ("%J%qD declared as nothrow, but it really throws",  
> t,
> +             prevailing);
> +          TREE_NO_WARNING (prevailing) = 1;
> +        }
>        }
>
>      pointer_set_insert (fixup_data->free_list, t);
> @@ -826,6 +844,7 @@ lto_fixup_tree (tree *tp, int *walk_subt
>       walk_tree (&TYPE_FIELDS (t), lto_fixup_tree, data, NULL);
>       walk_tree (&TYPE_BINFO (t), lto_fixup_tree, data, NULL);
>       break;
> +
>     case TREE_BINFO:
>       {
>    tree base;
> @@ -848,11 +867,13 @@ lto_fixup_tree (tree *tp, int *walk_subt
>      }
>       }
>       break;
> +
>     case VAR_DECL:
>       walk_tree (&DECL_INITIAL (t), lto_fixup_tree, data, NULL);
>       break;
> +
>     default:
> -      ;
> +      break;
>     }
>   return NULL;
> }
> @@ -1033,7 +1054,12 @@ lto_main (int debug_p ATTRIBUTE_UNUSED)
>
>   lto_fixup_decls (all_file_decl_data);
>
> -  /* FIXME!!! This loop needs to be changed to use the pass manager  
> to
> +  /* Skip over the rest if any errors were found.  FIXME lto, this
> +     should be reorganized to use the pass manager.  */
> +  if (errorcount)
> +    goto out;
> +
> +  /* FIXME lto. This loop needs to be changed to use the pass  
> manager to
>      call the ipa passes directly.  */
>   for (i = 0; i < j; i++)
>     {
> @@ -1124,6 +1150,7 @@ lto_main (int debug_p ATTRIBUTE_UNUSED)
>       XDELETEVEC (output_files);
>     }
>
> +out:
>   bitmap_obstack_release (&lto_bitmap_obstack);
> }
>
> Index: lto/Make-lang.in
> ===================================================================
> --- lto/Make-lang.in    (revision 141708)
> +++ lto/Make-lang.in    (working copy)
> @@ -91,13 +91,13 @@ LTO_TREE_H = lto/lto-tree.h $(PLUGIN_API
> lto/lto-lang.o: lto/lto-lang.c $(CONFIG_H) coretypes.h debug.h \
>    flags.h $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(SYSTEM_H) \
>    $(TM_H) $(LTO_TREE_H) $(LTO_H) $(GIMPLE_H) \
> -    gtype-lto.h gt-lto-lto-lang.h except.h libfuncs.h lto/common.h \
> -    lto-tree-in.h
> +    gtype-lto.h gt-lto-lto-lang.h lto/common.h lto-tree-in.h
> lto/lto.o: lto/lto.c $(CONFIG_H) $(CGRAPH_H) coretypes.h \
>    $(GGC_H) opts.h $(SYSTEM_H) toplev.h $(TM_H) $(LTO_H) langhooks.h \
>    $(LTO_TREE_H) dwarf2out.h tree-ssa-operands.h gt-lto-lto.h \
>    lto-section.h $(LTO_SECTION_IN_H) tree-pass.h $ 
> (LTO_SECTION_OUT_H) \
> -    pointer-set.h vec.h $(BITMAP_H) $(IPA_PROP_H) lto/common.h
> +    pointer-set.h vec.h $(BITMAP_H) $(IPA_PROP_H) lto/common.h \
> +    diagnostic.h
> lto/lto-elf.o: lto/lto-elf.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
>    toplev.h $(LTO_H) $(TM_H)
> lto/common.o: lto/common.h
> Index: lto/lto-lang.c
> ===================================================================
> --- lto/lto-lang.c    (revision 141708)
> +++ lto/lto-lang.c    (working copy)
> @@ -35,8 +35,6 @@ Boston, MA 02110-1301, USA.  */
> #include "tree-inline.h"
> #include "gimple.h"
> #include "toplev.h"
> -#include "libfuncs.h"
> -#include "except.h"
> #include "lto/common.h"
> #include "lto-tree-in.h"
>
> @@ -665,8 +663,6 @@ lto_init_options (unsigned int argc ATTR
>      decisions about what to output.  */
>   flag_unit_at_a_time = 1;
>
> -  /* Enable exceptions by default.  */
> -  flag_exceptions = 1;
>
>   return CL_LTO;
> }
> @@ -980,30 +976,6 @@ lto_build_c_type_nodes (void)
> }
>
>
> -/* Return the runtime type for type T.  For LTO, we assume that each
> -   front end has generated the appropriate runtime types (see
> -   output_eh_region), so there is nothing for us to do here.  */
> -
> -static tree
> -lto_eh_runtime_type (tree t)
> -{
> -  return t;
> -}
> -
> -
> -/* Initialize EH support.  */
> -
> -static void
> -lto_init_eh (void)
> -{
> -  eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
> -                         ? "__gcc_personality_sj0"
> -                         : "__gcc_personality_v0");
> -  default_init_unwind_resume_libfunc ();
> -  lang_eh_runtime_type = lto_eh_runtime_type;
> -}
> -
> -
> /* Perform LTO-specific initialization.  */
>
> static bool
> @@ -1055,9 +1027,6 @@ lto_init (void)
>   lto_global_var_decls = VEC_alloc (tree, gc, 256);
>   in_lto_p = true;
>
> -  if (flag_exceptions)
> -    lto_init_eh ();
> -
>   return true;
> }
>
> Index: Makefile.in
> ===================================================================
> --- Makefile.in    (revision 141708)
> +++ Makefile.in    (working copy)
> @@ -2093,7 +2093,8 @@ lto-function-in.o: lto-function-in.c $(C
>    $(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree-iterator.h tree- 
> pass.h \
>    tree-flow.h $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H)  
> except.h \
>    debug.h $(TIMEVAR_H) $(LTO_TAGS_H) lto-tree-flags.def $ 
> (LTO_TREE_IN_H) \
> -   lto-tree-tags.def $(LTO_SECTION_IN_H)  output.h dwarf2asm.h  
> dwarf2out.h
> +   lto-tree-tags.def $(LTO_SECTION_IN_H)  output.h dwarf2asm.h  
> dwarf2out.h \
> +   libfuncs.h
> lto-function-out.o : lto-function-out.c $(CONFIG_H) $(SYSTEM_H)  
> coretypes.h \
>    $(TM_H) $(TOPLEV_H) $(TREE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H)  
> input.h \
>    $(VARRAY_H) $(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree- 
> iterator.h \



More information about the Gcc-patches mailing list