This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lto] Support mixed EH settings
- From: Diego Novillo <dnovillo at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 9 Nov 2008 18:21:09 -0500
- Subject: [lto] Support mixed EH settings
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).
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 \