[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 (<o_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