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]

Re: [lto] Support mixed EH settings




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 \


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