This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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 (&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 \


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]