diff options
39 files changed, 503 insertions, 140 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 06b5c43..21bf315 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,54 @@ +2009-09-13 Richard Guenther <rguenther@suse.de> + Rafael Avila de Espindola <espindola@google.com> + + * langhooks-def.h (LANG_HOOKS_EH_RUNTIME_TYPE): Define. + (LANG_HOOKS_EH_PERSONALITY): Likewise. + (LANG_HOOKS_INITIALIZER): Adjust. + (lhd_pass_through_t): Declare. + * langhooks.h (struct lang_hooks): Add eh_runtime_type and + eh_personality. + * langhooks.c (lhd_pass_through_t): New function. + * dwarf2out.c (output_call_frame_info, dwarf2out_do_cfi_startproc, + dwarf2out_begin_prologue): Use personality from current_function_decl. + * expr.h (get_personality_function): Declare. + * expr.c (get_personality_function): New function. + (build_personality_function): Likewise. + * libfuncs.h (libfunc_index): Remove LTI_eh_personality. + (eh_personality_libfunc): Remove. + * optabs.c (build_libfunc_function): New function split out from ... + (init_one_libfunc): ... here. + * tree.h (DECL_FUNCTION_PERSONALITY): New. + (tree_function_decl): Add personality. + (lhd_gcc_personality): Declare. + (build_personality_function): Likewise. + * tree.c (gcc_eh_personality_decl): New. + (lhd_gcc_personality): New function. + * except.h (lang_eh_runtime_type): Remove. + (enum eh_personality_kind): New. + (build_personality_function): Declare. + (function_needs_eh_personality): Declare. + * except.c (lang_eh_runtime_type): Remove. + (function_needs_eh_personality): New function. + (add_type_for_runtime): Call lang_hooks.type_for_runtime instead. + (sjlj_emit_function_enter, output_function_exception_table): + Use personality from current_function_decl. + * tree-eh.c (lower_eh_constructs): Set DECL_FUNCTION_PERSONALITY. + * tree-inline.c (tree_can_inline_p): Do not inline across different + EH personalities. + (expand_call_inline): Likewise. Adjust the callers EH personality. + (tree_function_versioning): Copy DECL_FUNCTION_PERSONALITY. + * cgraph.c (cgraph_add_new_function): Set DECL_FUNCTION_PERSONALITY. + * Makefile.in (cgraph.o): Add $(EXCEPT_H) dependency. + (c-parser.o): Likewise + * c-tree.h (c_eh_initialized_p): Remove. + (c_maybe_initialize_eh): Likewise. + * c-decl.c (finish_decl): Don't call c_maybe_initialize_eh. + (finish_decl): Don't call c_maybe_initialize_eh. + (c_eh_initialized_p): Remove. + (c_maybe_initialize_eh): Likewise. + * c-parser.c (c_parser_omp_construct): Likewise. + (c_parse_file): Initialize exception handling. + 2009-09-13 Kai Tietz <kai.tietz@onevision.com> * config.gcc (tm_file): Remove i386/biarch32.h diff --git a/gcc/Makefile.in b/gcc/Makefile.in index bd1c7f0..d89fb2a 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1909,7 +1909,7 @@ c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ c-parser.o : c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ $(GGC_H) $(TIMEVAR_H) $(C_TREE_H) $(INPUT_H) $(FLAGS_H) $(TOPLEV_H) output.h \ $(CPPLIB_H) gt-c-parser.h $(RTL_H) langhooks.h $(C_COMMON_H) $(C_PRAGMA_H) \ - vec.h $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) + vec.h $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) $(EXCEPT_H) srcextra: gcc.srcextra lang.srcextra @@ -2767,7 +2767,7 @@ simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ langhooks.h $(TOPLEV_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \ gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \ - $(TREE_INLINE_H) $(TREE_DUMP_H) $(TREE_FLOW_H) value-prof.h + $(TREE_INLINE_H) $(TREE_DUMP_H) $(TREE_FLOW_H) value-prof.h $(EXCEPT_H) cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h $(TREE_INLINE_H) $(TOPLEV_H) $(FLAGS_H) $(GGC_H) \ $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \ diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9ef2feb..7d4d8aa 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,14 @@ +2009-09-13 Richard Guenther <rguenther@suse.de> + Rafael Avila de Espindola <espindola@google.com> + + * gcc-interface/misc.c (gnat_init_gcc_eh): Do not set + lang_eh_runtime_type. + (LANG_HOOKS_EH_PERSONALITY): Define. + (gnat_eh_personality_decl): New. + (gnat_eh_personality): Likewise. + * Make-lang.in (misc.o): Add gt-ada-misc.h dependency. + * config-lang.in (gtfiles): Add misc.c. + 2009-09-10 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> PR ada/18302 diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in index d0eb5e8..163274c 100644 --- a/gcc/ada/gcc-interface/Make-lang.in +++ b/gcc/ada/gcc-interface/Make-lang.in @@ -1072,7 +1072,8 @@ ada/misc.o : ada/gcc-interface/misc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(LANGHOOKS_DEF_H) opts.h options.h $(TREE_INLINE_H) \ ada/gcc-interface/ada.h ada/adadecode.h ada/types.h ada/atree.h \ ada/elists.h ada/namet.h ada/nlists.h ada/stringt.h ada/uintp.h ada/fe.h \ - ada/sinfo.h ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h + ada/sinfo.h ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h \ + gt-ada-misc.h $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@ ada/targtyps.o : ada/gcc-interface/targtyps.c $(CONFIG_H) $(SYSTEM_H) \ diff --git a/gcc/ada/gcc-interface/config-lang.in b/gcc/ada/gcc-interface/config-lang.in index 5825398..b4a28be 100644 --- a/gcc/ada/gcc-interface/config-lang.in +++ b/gcc/ada/gcc-interface/config-lang.in @@ -32,7 +32,7 @@ boot_language_boot_flags='ADAFLAGS="$(BOOT_ADAFLAGS)"' compilers="gnat1\$(exeext)" -gtfiles="\$(srcdir)/ada/gcc-interface/ada-tree.h \$(srcdir)/ada/gcc-interface/gigi.h \$(srcdir)/ada/gcc-interface/decl.c \$(srcdir)/ada/gcc-interface/trans.c \$(srcdir)/ada/gcc-interface/utils.c" +gtfiles="\$(srcdir)/ada/gcc-interface/ada-tree.h \$(srcdir)/ada/gcc-interface/gigi.h \$(srcdir)/ada/gcc-interface/decl.c \$(srcdir)/ada/gcc-interface/trans.c \$(srcdir)/ada/gcc-interface/utils.c \$(srcdir)/ada/gcc-interface/misc.c" outputs="ada/gcc-interface/Makefile ada/Makefile" diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c index f39a60e..261351f 100644 --- a/gcc/ada/gcc-interface/misc.c +++ b/gcc/ada/gcc-interface/misc.c @@ -79,6 +79,7 @@ static void gnat_parse_file (int); static void internal_error_function (const char *, va_list *); static tree gnat_type_max_size (const_tree); static void gnat_get_subrange_bounds (const_tree, tree *, tree *); +static tree gnat_eh_personality (void); /* Definitions for our language-specific hooks. */ @@ -129,7 +130,9 @@ static void gnat_get_subrange_bounds (const_tree, tree *, tree *); #undef LANG_HOOKS_ATTRIBUTE_TABLE #define LANG_HOOKS_ATTRIBUTE_TABLE gnat_internal_attribute_table #undef LANG_HOOKS_BUILTIN_FUNCTION -#define LANG_HOOKS_BUILTIN_FUNCTION gnat_builtin_function +#define LANG_HOOKS_BUILTIN_FUNCTION gnat_builtin_function +#undef LANG_HOOKS_EH_PERSONALITY +#define LANG_HOOKS_EH_PERSONALITY gnat_eh_personality struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; @@ -431,11 +434,7 @@ gnat_init_gcc_eh (void) right exception regions. */ using_eh_for_cleanups (); - eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS - ? "__gnat_eh_personality_sj" - : "__gnat_eh_personality"); lang_eh_type_covers = gnat_eh_type_covers; - lang_eh_runtime_type = gnat_return_tree; default_init_unwind_resume_libfunc (); /* Turn on -fexceptions and -fnon-call-exceptions. The first one triggers @@ -811,3 +810,19 @@ fp_size_to_prec (int size) gcc_unreachable (); } + +static GTY(()) tree gnat_eh_personality_decl; + +static tree +gnat_eh_personality (void) +{ + if (!gnat_eh_personality_decl) + gnat_eh_personality_decl + = build_personality_function (USING_SJLJ_EXCEPTIONS + ? "__gnat_eh_personality_sj" + : "__gnat_eh_personality"); + + return gnat_eh_personality_decl; +} + +#include "gt-ada-misc.h" diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 1bc9791..ed8863d 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -92,9 +92,6 @@ tree pending_invalid_xref; /* File and line to appear in the eventual error message. */ location_t pending_invalid_xref_location; -/* True means we've initialized exception handling. */ -bool c_eh_initialized_p; - /* The file and line that the prototype came from if this is an old-style definition; used for diagnostics in store_parm_decls_oldstyle. */ @@ -2365,7 +2362,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) TREE_USED (olddecl) = 1; /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. - But preserve OLDDECL's DECL_UID and DECL_CONTEXT. */ + But preserve OLDDECL's DECL_UID, DECL_CONTEXT and + DECL_ARGUMENTS (if appropriate). */ { unsigned olddecl_uid = DECL_UID (olddecl); tree olddecl_context = DECL_CONTEXT (olddecl); @@ -4043,23 +4041,6 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, return tem; } -/* Initialize EH if not initialized yet and exceptions are enabled. */ - -void -c_maybe_initialize_eh (void) -{ - if (!flag_exceptions || c_eh_initialized_p) - return; - - c_eh_initialized_p = true; - eh_personality_libfunc - = init_one_libfunc (USING_SJLJ_EXCEPTIONS - ? "__gcc_personality_sj0" - : "__gcc_personality_v0"); - default_init_unwind_resume_libfunc (); - using_eh_for_cleanups (); -} - /* Finish processing of a declaration; install its initial value. If ORIGTYPE is not NULL_TREE, it is the original type of INIT. @@ -4360,9 +4341,6 @@ finish_decl (tree decl, location_t init_loc, tree init, TREE_USED (decl) = 1; TREE_USED (cleanup_decl) = 1; - /* Initialize EH, if we've been told to do so. */ - c_maybe_initialize_eh (); - push_cleanup (decl, cleanup, false); } } diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 43b0c8c..ddb81e1 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "cgraph.h" #include "plugin.h" +#include "except.h" /* Initialization routine for this file. */ @@ -8489,12 +8490,6 @@ c_parser_omp_construct (c_parser *parser) p_kind = c_parser_peek_token (parser)->pragma_kind; c_parser_consume_pragma (parser); - /* For all constructs below except #pragma omp atomic - MUST_NOT_THROW catch handlers are needed when exceptions - are enabled. */ - if (p_kind != PRAGMA_OMP_ATOMIC) - c_maybe_initialize_eh (); - switch (p_kind) { case PRAGMA_OMP_ATOMIC: @@ -8607,6 +8602,13 @@ c_parse_file (void) the_parser = GGC_NEW (c_parser); *the_parser = tparser; + /* Initialize EH, if we've been told to do so. */ + if (flag_exceptions) + { + default_init_unwind_resume_libfunc (); + using_eh_for_cleanups (); + } + c_parser_translation_unit (the_parser); the_parser = NULL; } diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 502e6ef..5c1ccb5 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -427,7 +427,6 @@ extern struct c_spot_bindings *c_get_switch_bindings (void); extern void c_release_switch_bindings (struct c_spot_bindings *); extern bool c_check_switch_jump_warnings (struct c_spot_bindings *, location_t, location_t); -extern void c_maybe_initialize_eh (void); extern void finish_decl (tree, location_t, tree, tree, tree); extern tree finish_enum (tree, tree, tree); extern void finish_function (void); @@ -589,9 +588,6 @@ extern int system_header_p; extern bool c_override_global_bindings_to_false; -/* True means we've initialized exception handling. */ -extern bool c_eh_initialized_p; - /* In c-decl.c */ extern void c_finish_incomplete_decl (tree); extern void c_write_global_declarations (void); diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 2f5bd2a..75447be 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -84,6 +84,7 @@ The callgraph: #include "tree-dump.h" #include "tree-flow.h" #include "value-prof.h" +#include "except.h" static void cgraph_node_remove_callers (struct cgraph_node *node); static inline void cgraph_edge_remove_caller (struct cgraph_edge *e); @@ -1953,6 +1954,12 @@ cgraph_add_new_function (tree fndecl, bool lowered) current_function_decl = NULL; break; } + + /* Set a personality if required and we already passed EH lowering. */ + if (lowered + && (function_needs_eh_personality (DECL_STRUCT_FUNCTION (fndecl)) + == eh_personality_lang)) + DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality (); } /* Return true if NODE can be made local for API change. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d6befec..a50e9fc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2009-09-13 Richard Guenther <rguenther@suse.de> + Rafael Avila de Espindola <espindola@google.com> + + * except.c (init_exception_processing): Do not set + lang_eh_runtime_type. + (choose_personality_routine): Do not set eh_personality_decl, + set pragma_java_exceptions. + * cp-lang.c (LANG_HOOKS_EH_RUNTIME_TYPE): Define. + (LANG_HOOKS_EH_PERSONALITY): Likewise. + (cp_eh_personality_decl): New. + (cp_eh_personality): Likewise. + * Make-lang.in (cp-lang.o): Add $(EXPR_H) and $(EXCEPT_H) + dependencies. + 2009-09-13 Wei Guozhi <carrot@google.com> PR c++/3187 diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index da5d8ac..861c93d 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -250,7 +250,7 @@ cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \ $(C_PRAGMA_H) toplev.h output.h input.h cp/operators.def $(TM_P_H) cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h debug.h langhooks.h \ $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-cp.h \ - $(DIAGNOSTIC_H) cp/cp-objcp-common.h + $(DIAGNOSTIC_H) cp/cp-objcp-common.h $(EXPR_H) $(EXCEPT_H) cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h \ output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(RTL_H) \ cp/operators.def $(TM_P_H) $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(C_PRAGMA_H) \ diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index f818e5b..9521eab 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -32,11 +32,14 @@ along with GCC; see the file COPYING3. If not see #include "debug.h" #include "cp-objcp-common.h" #include "hashtab.h" +#include "except.h" +#include "expr.h" enum c_language_kind c_language = clk_cxx; static void cp_init_ts (void); static const char * cxx_dwarf_name (tree t, int verbosity); static enum classify_record cp_classify_record (tree type); +static tree cp_eh_personality (void); /* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h; consequently, there should be very few hooks below. */ @@ -71,6 +74,10 @@ static enum classify_record cp_classify_record (tree type); #define LANG_HOOKS_FOLD_OBJ_TYPE_REF cp_fold_obj_type_ref #undef LANG_HOOKS_INIT_TS #define LANG_HOOKS_INIT_TS cp_init_ts +#undef LANG_HOOKS_EH_PERSONALITY +#define LANG_HOOKS_EH_PERSONALITY cp_eh_personality +#undef LANG_HOOKS_EH_RUNTIME_TYPE +#define LANG_HOOKS_EH_RUNTIME_TYPE build_eh_type_type /* Each front end provides its own lang hook initializer. */ struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; @@ -145,4 +152,26 @@ finish_file (void) { } +static GTY(()) tree cp_eh_personality_decl; + +static tree +cp_eh_personality (void) +{ + if (!cp_eh_personality_decl) + { + if (!pragma_java_exceptions) + cp_eh_personality_decl + = build_personality_function (USING_SJLJ_EXCEPTIONS + ? "__gxx_personality_sj0" + : "__gxx_personality_v0"); + else + cp_eh_personality_decl + = build_personality_function (USING_SJLJ_EXCEPTIONS + ? "__gcj_personality_sj0" + : "__gcj_personality_v0"); + } + + return cp_eh_personality_decl; +} + #include "gtype-cp.h" diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ea3b4bf..c720a56 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4521,6 +4521,7 @@ extern void choose_personality_routine (enum languages); extern tree eh_type_info (tree); extern tree begin_eh_spec_block (void); extern void finish_eh_spec_block (tree, tree); +extern tree build_eh_type_type (tree); /* in expr.c */ extern tree cplus_expand_constant (tree); diff --git a/gcc/cp/except.c b/gcc/cp/except.c index fdef154..588c2ee 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -43,7 +43,6 @@ along with GCC; see the file COPYING3. If not see static void push_eh_cleanup (tree); static tree prepare_eh_type (tree); -static tree build_eh_type_type (tree); static tree do_begin_catch (void); static int dtor_nothrow (tree); static tree do_end_catch (tree); @@ -78,15 +77,11 @@ init_exception_processing (void) call_unexpected_node = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp); - eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS - ? "__gxx_personality_sj0" - : "__gxx_personality_v0"); if (targetm.arm_eabi_unwinder) unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup"); else default_init_unwind_resume_libfunc (); - lang_eh_runtime_type = build_eh_type_type; lang_protect_cleanup_actions = &cp_protect_cleanup_actions; } @@ -143,7 +138,7 @@ eh_type_info (tree type) /* Build the address of a typeinfo decl for use in the runtime matching field of the exception model. */ -static tree +tree build_eh_type_type (tree type) { tree exp = eh_type_info (type); @@ -313,7 +308,7 @@ decl_is_java_type (tree decl, int err) /* Select the personality routine to be used for exception handling, or issue an error if we need two different ones in the same translation unit. - ??? At present eh_personality_libfunc is set to + ??? At present eh_personality_decl is set to __gxx_personality_(sj|v)0 in init_exception_processing - should it be done here instead? */ void @@ -354,9 +349,7 @@ choose_personality_routine (enum languages lang) case lang_java: state = chose_java; terminate_node = built_in_decls [BUILT_IN_ABORT]; - eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS - ? "__gcj_personality_sj0" - : "__gcj_personality_v0"); + pragma_java_exceptions = true; break; default: diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 62459e2..6f0b965 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -216,6 +216,10 @@ static GTY(()) section *debug_str_section; static GTY(()) section *debug_ranges_section; static GTY(()) section *debug_frame_section; +/* Personality decl of current unit. Used only when assembler does not support + personality CFI. */ +static GTY(()) rtx current_unit_personality; + /* How to start an assembler comment. */ #ifndef ASM_COMMENT_START #define ASM_COMMENT_START ";#" @@ -3599,6 +3603,7 @@ output_call_frame_info (int for_eh) int per_encoding = DW_EH_PE_absptr; int lsda_encoding = DW_EH_PE_absptr; int return_reg; + rtx personality = NULL; int dw_cie_version; /* Don't emit a CIE if there won't be any FDEs. */ @@ -3684,6 +3689,8 @@ output_call_frame_info (int for_eh) augmentation[0] = 0; augmentation_size = 0; + + personality = current_unit_personality; if (for_eh) { char *p; @@ -3703,11 +3710,11 @@ output_call_frame_info (int for_eh) lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0); p = augmentation + 1; - if (eh_personality_libfunc) + if (personality) { *p++ = 'P'; augmentation_size += 1 + size_of_encoded_value (per_encoding); - assemble_external_libcall (eh_personality_libfunc); + assemble_external_libcall (personality); } if (any_lsda_needed) { @@ -3726,7 +3733,7 @@ output_call_frame_info (int for_eh) } /* Ug. Some platforms can't do unaligned dynamic relocations at all. */ - if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned) + if (personality && per_encoding == DW_EH_PE_aligned) { int offset = ( 4 /* Length */ + 4 /* CIE Id */ @@ -3760,12 +3767,12 @@ output_call_frame_info (int for_eh) if (augmentation[0]) { dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size"); - if (eh_personality_libfunc) + if (personality) { dw2_asm_output_data (1, per_encoding, "Personality (%s)", eh_data_format_name (per_encoding)); dw2_asm_output_encoded_addr_rtx (per_encoding, - eh_personality_libfunc, + personality, true, NULL); } @@ -3824,13 +3831,14 @@ dwarf2out_do_cfi_startproc (bool second) { int enc; rtx ref; + rtx personality = get_personality_function (current_function_decl); fprintf (asm_out_file, "\t.cfi_startproc\n"); - if (eh_personality_libfunc) + if (personality) { enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1); - ref = eh_personality_libfunc; + ref = personality; /* ??? The GAS support isn't entirely consistent. We have to handle indirect support ourselves, but PC-relative is done @@ -3873,6 +3881,7 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED, char label[MAX_ARTIFICIAL_LABEL_BYTES]; char * dup_label; dw_fde_ref fde; + rtx personality; section *fnsec; current_function_func_begin_label = NULL; @@ -3967,8 +3976,17 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED, dwarf2out_source_line (line, file, 0, true); #endif + personality = get_personality_function (current_function_decl); if (dwarf2out_do_cfi_asm ()) dwarf2out_do_cfi_startproc (false); + else + { + if (!current_unit_personality || current_unit_personality == personality) + current_unit_personality = personality; + else + sorry ("Multiple EH personalities are supported only with assemblers " + "supporting .cfi.personality directive."); + } } /* Output a marker (i.e. a label) for the absolute end of the generated code diff --git a/gcc/except.c b/gcc/except.c index c97928e..9b6c24e 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -92,9 +92,6 @@ gimple (*lang_protect_cleanup_actions) (void); /* Return true if type A catches type B. */ int (*lang_eh_type_covers) (tree a, tree b); -/* Map a type to a runtime object to match type. */ -tree (*lang_eh_runtime_type) (tree); - /* A hash table of label to region number. */ struct GTY(()) ehl_map_entry { @@ -1696,7 +1693,7 @@ add_type_for_runtime (tree type) TREE_HASH (type), INSERT); if (*slot == NULL) { - tree runtime = (*lang_eh_runtime_type) (type); + tree runtime = lang_hooks.eh_runtime_type (type); *slot = tree_cons (type, runtime, NULL_TREE); } } @@ -2424,6 +2421,7 @@ sjlj_emit_function_enter (rtx dispatch_label) { rtx fn_begin, fc, mem, seq; bool fn_begin_outside_block; + rtx personality = get_personality_function (current_function_decl); fc = crtl->eh.sjlj_fc; @@ -2432,9 +2430,9 @@ sjlj_emit_function_enter (rtx dispatch_label) /* We're storing this libcall's address into memory instead of calling it directly. Thus, we must call assemble_external_libcall here, as we can not depend on emit_library_call to do it for us. */ - assemble_external_libcall (eh_personality_libfunc); + assemble_external_libcall (personality); mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs); - emit_move_insn (mem, eh_personality_libfunc); + emit_move_insn (mem, personality); mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs); if (crtl->uses_eh_lsda) @@ -4394,7 +4392,7 @@ output_ttype (tree type, int tt_format, int tt_format_size) static void output_one_function_exception_table (const char * ARG_UNUSED (fnname), - int section) + int section, rtx ARG_UNUSED (personality)) { int tt_format, cs_format, lp_format, i, n; #ifdef HAVE_AS_LEB128 @@ -4410,7 +4408,7 @@ output_one_function_exception_table (const char * ARG_UNUSED (fnname), #ifdef TARGET_UNWIND_INFO /* TODO: Move this into target file. */ fputs ("\t.personality\t", asm_out_file); - output_addr_const (asm_out_file, eh_personality_libfunc); + output_addr_const (asm_out_file, personality); fputs ("\n\t.handlerdata\n", asm_out_file); /* Note that varasm still thinks we're in the function's code section. The ".endp" directive that will immediately follow will take us back. */ @@ -4580,16 +4578,18 @@ output_one_function_exception_table (const char * ARG_UNUSED (fnname), void output_function_exception_table (const char * ARG_UNUSED (fnname)) { + rtx personality = get_personality_function (current_function_decl); + /* Not all functions need anything. */ if (! crtl->uses_eh_lsda) return; - if (eh_personality_libfunc) - assemble_external_libcall (eh_personality_libfunc); + if (personality) + assemble_external_libcall (personality); - output_one_function_exception_table (fnname, 0); + output_one_function_exception_table (fnname, 0, personality); if (crtl->eh.call_site_record[1] != NULL) - output_one_function_exception_table (fnname, 1); + output_one_function_exception_table (fnname, 1, personality); switch_to_section (current_function_section ()); } @@ -4606,6 +4606,70 @@ get_eh_throw_stmt_table (struct function *fun) return fun->eh->throw_stmt_table; } +/* Return true if the function deeds a EH personality function. */ + +enum eh_personality_kind +function_needs_eh_personality (struct function *fn) +{ + struct eh_region_d *i; + int depth = 0; + enum eh_personality_kind kind = eh_personality_none; + + i = fn->eh->region_tree; + if (!i) + return eh_personality_none; + + while (1) + { + switch (i->type) + { + case ERT_TRY: + case ERT_THROW: + /* Do not need a EH personality function. */ + break; + + case ERT_MUST_NOT_THROW: + /* Always needs a EH personality function. */ + return eh_personality_lang; + + case ERT_CLEANUP: + /* Can do with any personality including the generic C one. */ + kind = eh_personality_any; + break; + + case ERT_CATCH: + case ERT_ALLOWED_EXCEPTIONS: + /* Always needs a EH personality function. The generic C + personality doesn't handle these even for empty type lists. */ + return eh_personality_lang; + + case ERT_UNKNOWN: + return eh_personality_lang; + } + /* If there are sub-regions, process them. */ + if (i->inner) + i = i->inner, depth++; + /* If there are peers, process them. */ + else if (i->next_peer) + i = i->next_peer; + /* Otherwise, step back up the tree to the next peer. */ + else + { + do + { + i = i->outer; + depth--; + if (i == NULL) + return kind; + } + while (i->next_peer == NULL); + i = i->next_peer; + } + } + + return kind; +} + /* Dump EH information to OUT. */ void diff --git a/gcc/except.h b/gcc/except.h index f332b2b..af63e98 100644 --- a/gcc/except.h +++ b/gcc/except.h @@ -217,9 +217,6 @@ extern gimple (*lang_protect_cleanup_actions) (void); /* Return true if type A catches type B. */ extern int (*lang_eh_type_covers) (tree a, tree b); -/* Map a type to a runtime object to match type. */ -extern tree (*lang_eh_runtime_type) (tree); - /* Just because the user configured --with-sjlj-exceptions=no doesn't mean that we can use call frame exceptions. Detect that the target @@ -277,3 +274,12 @@ extern int num_eh_regions (void); extern bitmap must_not_throw_labels (void); extern struct eh_region_d *redirect_eh_edge_to_label (struct edge_def *, tree, bool, bool, int); extern int get_next_region_sharing_label (int); + +enum eh_personality_kind { + eh_personality_none, + eh_personality_any, + eh_personality_lang +}; + +extern enum eh_personality_kind +function_needs_eh_personality (struct function *); @@ -10214,4 +10214,52 @@ const_vector_from_tree (tree exp) return gen_rtx_CONST_VECTOR (mode, v); } + + +/* Build a decl for a EH personality function named NAME. */ + +tree +build_personality_function (const char *name) +{ + tree decl, type; + + type = build_function_type_list (integer_type_node, integer_type_node, + long_long_unsigned_type_node, + ptr_type_node, ptr_type_node, NULL_TREE); + decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, + get_identifier (name), type); + DECL_ARTIFICIAL (decl) = 1; + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + + /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with + are the flags assigned by targetm.encode_section_info. */ + SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL); + + return decl; +} + +/* Extracts the personality function of DECL and returns the corresponding + libfunc. */ + +rtx +get_personality_function (tree decl) +{ + tree personality = DECL_FUNCTION_PERSONALITY (decl); + enum eh_personality_kind pk; + + pk = function_needs_eh_personality (DECL_STRUCT_FUNCTION (decl)); + if (pk == eh_personality_none) + return NULL; + + if (!personality + && pk == eh_personality_any) + personality = lang_hooks.eh_personality (); + + if (pk == eh_personality_lang) + gcc_assert (personality != NULL_TREE); + + return XEXP (DECL_RTL (personality), 0); +} + #include "gt-expr.h" @@ -814,6 +814,12 @@ extern void init_all_optabs (void); extern rtx init_one_libfunc (const char *); extern rtx set_user_assembler_libfunc (const char *, const char *); +/* Build a decl for a libfunc named NAME. */ +extern tree build_libfunc_function (const char *); + +/* Get the personality libfunc for a function decl. */ +rtx get_personality_function (tree); + extern int vector_mode_valid_p (enum machine_mode); #endif /* GCC_EXPR_H */ diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 903f25d..7cf6e86 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2009-09-13 Richard Guenther <rguenther@suse.de> + Rafael Avila de Espindola <espindola@google.com> + + * f95-lang.c (gfc_maybe_initialize_eh): Do not init + eh_personality_libfunc. + 2009-09-11 Janus Weil <janus@gcc.gnu.org> PR fortran/41242 diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index e061538..3d94fd6 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -1155,10 +1155,6 @@ gfc_maybe_initialize_eh (void) return; gfc_eh_initialized_p = true; - eh_personality_libfunc - = init_one_libfunc (USING_SJLJ_EXCEPTIONS - ? "__gcc_personality_sj0" - : "__gcc_personality_v0"); default_init_unwind_resume_libfunc (); using_eh_for_cleanups (); } diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 569b5fe..6b7d930 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,13 @@ +2009-09-13 Richard Guenther <rguenther@suse.de> + Rafael Avila de Espindola <espindola@google.com> + + * decl.c (do_nothing): Remove. + (java_init_decl_processing): Do not set lang_eh_runtime_type. + * Make-lang.in (lang.o): Add $(EXCEPT_H) dependency. + * lang.c (java_eh_personality): New. + (java_eh_personality_decl): Likewise. + (LANG_HOOKS_EH_PERSONALITY): Define. + 2009-09-03 Diego Novillo <dnovillo@google.com> * lang.c (lang_hooks): Remove const qualifier. diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in index ff330fd..a56e2b6 100644 --- a/gcc/java/Make-lang.in +++ b/gcc/java/Make-lang.in @@ -284,7 +284,7 @@ java/jvgenmain.o: java/jvgenmain.c $(CONFIG_H) $(JAVA_TREE_H) $(SYSTEM_H) \ coretypes.h $(TM_H) intl.h java/lang.o: java/lang.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h input.h \ toplev.h $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(EXPR_H) $(DIAGNOSTIC_H) \ - langhooks.h $(LANGHOOKS_DEF_H) gt-java-lang.h opts.h options.h + langhooks.h $(LANGHOOKS_DEF_H) gt-java-lang.h opts.h options.h $(EXCEPT_H) java/mangle.o: java/mangle.c $(CONFIG_H) java/jcf.h $(JAVA_TREE_H) $(SYSTEM_H) \ coretypes.h $(TM_H) toplev.h $(GGC_H) gt-java-mangle.h $(LANGHOOKS_DEF_H) java/mangle_name.o: java/mangle_name.c $(CONFIG_H) java/jcf.h $(JAVA_TREE_H) \ diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 4ab67d6..c9ccc9d 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -510,12 +510,6 @@ create_primitive_vtable (const char *name) return r; } -static tree -do_nothing (tree t) -{ - return t; -} - /* Parse the version string and compute the ABI version number. */ static void parse_version (void) @@ -1195,16 +1189,12 @@ java_init_decl_processing (void) 0, NOT_BUILT_IN, NULL, NULL_TREE); /* Initialize variables for except.c. */ - eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS - ? "__gcj_personality_sj0" - : "__gcj_personality_v0"); + if (targetm.arm_eabi_unwinder) unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup"); else default_init_unwind_resume_libfunc (); - lang_eh_runtime_type = do_nothing; - initialize_builtins (); soft_fmod_node = built_in_decls[BUILT_IN_FMOD]; diff --git a/gcc/java/lang.c b/gcc/java/lang.c index d97b508..504d029 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -45,6 +45,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "tree-dump.h" #include "opts.h" #include "options.h" +#include "except.h" static bool java_init (void); static void java_finish (void); @@ -64,6 +65,8 @@ static bool java_decl_ok_for_sibcall (const_tree); static enum classify_record java_classify_record (tree type); +static tree java_eh_personality (void); + #ifndef TARGET_OBJECT_SUFFIX # define TARGET_OBJECT_SUFFIX ".o" #endif @@ -158,6 +161,9 @@ struct GTY(()) language_function { #undef LANG_HOOKS_ATTRIBUTE_TABLE #define LANG_HOOKS_ATTRIBUTE_TABLE java_attribute_table +#undef LANG_HOOKS_EH_PERSONALITY +#define LANG_HOOKS_EH_PERSONALITY java_eh_personality + /* Each front end provides its own. */ struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; @@ -880,4 +886,18 @@ java_classify_record (tree type) return RECORD_IS_CLASS; } +static GTY(()) tree java_eh_personality_decl; + +static tree +java_eh_personality (void) +{ + if (!java_eh_personality_decl) + java_eh_personality_decl + = build_personality_function (USING_SJLJ_EXCEPTIONS + ? "__gcj_personality_sj0" + : "__gcj_personality_v0"); + + return java_eh_personality_decl; +} + #include "gt-java-lang.h" diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index 63a0dcd..dc4fdee 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -40,6 +40,7 @@ extern void lhd_do_nothing (void); extern void lhd_do_nothing_t (tree); extern void lhd_do_nothing_i (int); extern void lhd_do_nothing_f (struct function *); +extern tree lhd_pass_through_t (tree); extern bool lhd_post_options (const char **); extern alias_set_type lhd_get_alias_set (tree); extern tree lhd_return_null_tree_v (void); @@ -107,6 +108,8 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *, #define LANG_HOOKS_EXPR_TO_DECL lhd_expr_to_decl #define LANG_HOOKS_TO_TARGET_CHARSET lhd_to_target_charset #define LANG_HOOKS_INIT_TS lhd_do_nothing +#define LANG_HOOKS_EH_PERSONALITY lhd_gcc_personality +#define LANG_HOOKS_EH_RUNTIME_TYPE lhd_pass_through_t /* Attribute hooks. */ #define LANG_HOOKS_ATTRIBUTE_TABLE NULL @@ -271,6 +274,8 @@ extern tree lhd_make_node (enum tree_code); LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \ LANG_HOOKS_INIT_TS, \ LANG_HOOKS_EXPR_TO_DECL, \ + LANG_HOOKS_EH_PERSONALITY, \ + LANG_HOOKS_EH_RUNTIME_TYPE, \ } #endif /* GCC_LANG_HOOKS_DEF_H */ diff --git a/gcc/langhooks.c b/gcc/langhooks.c index 7d2c0b0..092a323 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -53,6 +53,13 @@ lhd_do_nothing_t (tree ARG_UNUSED (t)) { } +/* Pass through (tree). */ +tree +lhd_pass_through_t (tree t) +{ + return t; +} + /* Do nothing (int). */ void diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 8342004..349a5d8 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -414,6 +414,12 @@ struct lang_hooks if in the process TREE_CONSTANT or TREE_SIDE_EFFECTS need updating. */ tree (*expr_to_decl) (tree expr, bool *tc, bool *se); + /* The EH personality function decl. */ + tree (*eh_personality) (void); + + /* Map a type to a runtime object to match type. */ + tree (*eh_runtime_type) (tree); + /* Whenever you add entries here, make sure you adjust langhooks-def.h and langhooks.c accordingly. */ }; diff --git a/gcc/libfuncs.h b/gcc/libfuncs.h index 70621cf..997ecb0 100644 --- a/gcc/libfuncs.h +++ b/gcc/libfuncs.h @@ -31,7 +31,6 @@ enum libfunc_index LTI_setbits, LTI_unwind_resume, - LTI_eh_personality, LTI_setjmp, LTI_longjmp, LTI_unwind_sjlj_register, @@ -61,7 +60,6 @@ extern GTY(()) rtx libfunc_table[LTI_MAX]; #define setbits_libfunc (libfunc_table[LTI_setbits]) #define unwind_resume_libfunc (libfunc_table[LTI_unwind_resume]) -#define eh_personality_libfunc (libfunc_table[LTI_eh_personality]) #define setjmp_libfunc (libfunc_table[LTI_setjmp]) #define longjmp_libfunc (libfunc_table[LTI_longjmp]) #define unwind_sjlj_register_libfunc (libfunc_table[LTI_unwind_sjlj_register]) diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index d499f0a..59317eb 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,17 @@ +2009-09-13 Richard Guenther <rguenther@suse.de> + Rafael Avila de Espindola <espindola@google.com> + + * objc-act.c (objc_eh_runtime_type): Export. + (objc_init_exceptions): Remove. Move warning code ... + (objc_begin_try_stmt): ... here + (objc_build_throw_stmt): ... and here. + (objc_eh_personality_decl): New. + (objc_eh_personality): New function. + * objc-act.h (objc_eh_runtime_type): Declare. + (objc_eh_personality): Likewise. + * objc-lang.c (LANG_HOOKS_EH_RUNTIME_TYPE): Define. + (LANG_HOOKS_EH_PERSONALITY): Likewise. + 2009-09-03 Diego Novillo <dnovillo@google.com> * objc-lang.c (lang_hooks): Remove const qualifier. diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 8b1a596..f695431 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -3483,50 +3483,32 @@ struct objc_try_context static struct objc_try_context *cur_try_context; +static GTY(()) tree objc_eh_personality_decl; + /* This hook, called via lang_eh_runtime_type, generates a runtime object that represents TYPE. For Objective-C, this is just the class name. */ /* ??? Isn't there a class object or some such? Is it easy to get? */ #ifndef OBJCPLUS -static tree +tree objc_eh_runtime_type (tree type) { return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names); } -#endif - -/* Initialize exception handling. */ -static void -objc_init_exceptions (void) +tree +objc_eh_personality (void) { - static bool done = false; - if (done) - return; - done = true; + if (!flag_objc_sjlj_exceptions + && !objc_eh_personality_decl) + objc_eh_personality_decl + = build_personality_function (USING_SJLJ_EXCEPTIONS + ? "__gnu_objc_personality_sj0" + : "__gnu_objc_personality_v0"); - if (flag_objc_sjlj_exceptions) - { - /* On Darwin, ObjC exceptions require a sufficiently recent - version of the runtime, so the user must ask for them explicitly. */ - if (!flag_objc_exceptions) - warning (0, "use %<-fobjc-exceptions%> to enable Objective-C " - "exception syntax"); - } -#ifndef OBJCPLUS - else - { - c_eh_initialized_p = true; - eh_personality_libfunc - = init_one_libfunc (USING_SJLJ_EXCEPTIONS - ? "__gnu_objc_personality_sj0" - : "__gnu_objc_personality_v0"); - default_init_unwind_resume_libfunc (); - using_eh_for_cleanups (); - lang_eh_runtime_type = objc_eh_runtime_type; - } -#endif + return objc_eh_personality_decl; } +#endif /* Build an EXC_PTR_EXPR, or the moral equivalent. In the case of Darwin, we'll arrange for it to be initialized (and associated with a binding) @@ -3824,7 +3806,14 @@ objc_begin_try_stmt (location_t try_locus, tree body) c->end_try_locus = input_location; cur_try_context = c; - objc_init_exceptions (); + if (flag_objc_sjlj_exceptions) + { + /* On Darwin, ObjC exceptions require a sufficiently recent + version of the runtime, so the user must ask for them explicitly. */ + if (!flag_objc_exceptions) + warning (0, "use %<-fobjc-exceptions%> to enable Objective-C " + "exception syntax"); + } if (flag_objc_sjlj_exceptions) objc_mark_locals_volatile (NULL); @@ -3973,7 +3962,14 @@ objc_build_throw_stmt (location_t loc, tree throw_expr) { tree args; - objc_init_exceptions (); + if (flag_objc_sjlj_exceptions) + { + /* On Darwin, ObjC exceptions require a sufficiently recent + version of the runtime, so the user must ask for them explicitly. */ + if (!flag_objc_exceptions) + warning (0, "use %<-fobjc-exceptions%> to enable Objective-C " + "exception syntax"); + } if (throw_expr == NULL) { diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h index fb92934..f0970f9 100644 --- a/gcc/objc/objc-act.h +++ b/gcc/objc/objc-act.h @@ -32,6 +32,8 @@ const char *objc_printable_name (tree, int); void objc_finish_file (void); tree objc_fold_obj_type_ref (tree, tree); int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *); +tree objc_eh_runtime_type (tree); +tree objc_eh_personality (void); /* NB: The remaining public functions are prototyped in c-common.h, for the benefit of stub-objc.c and objc-act.c. */ diff --git a/gcc/objc/objc-lang.c b/gcc/objc/objc-lang.c index 98f46d7..acb1c84 100644 --- a/gcc/objc/objc-lang.c +++ b/gcc/objc/objc-lang.c @@ -51,6 +51,13 @@ static void objc_init_ts (void); #undef LANG_HOOKS_INIT_TS #define LANG_HOOKS_INIT_TS objc_init_ts +#ifndef OBJCPLUS +#undef LANG_HOOKS_EH_PERSONALITY +#define LANG_HOOKS_EH_PERSONALITY objc_eh_personality +#undef LANG_HOOKS_EH_RUNTIME_TYPE +#define LANG_HOOKS_EH_RUNTIME_TYPE objc_eh_runtime_type +#endif + /* Each front end provides its own lang hook initializer. */ struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; diff --git a/gcc/optabs.c b/gcc/optabs.c index 61d8bcf..35f95f2 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6023,6 +6023,28 @@ libfunc_decl_eq (const void *entry1, const void *entry2) return DECL_NAME ((const_tree) entry1) == (const_tree) entry2; } +/* Build a decl for a libfunc named NAME. */ + +tree +build_libfunc_function (const char *name) +{ + tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, + get_identifier (name), + build_function_type (integer_type_node, NULL_TREE)); + /* ??? We don't have any type information except for this is + a function. Pretend this is "int foo()". */ + DECL_ARTIFICIAL (decl) = 1; + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + gcc_assert (DECL_ASSEMBLER_NAME (decl)); + + /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with + are the flags assigned by targetm.encode_section_info. */ + SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL); + + return decl; +} + rtx init_one_libfunc (const char *name) { @@ -6043,19 +6065,7 @@ init_one_libfunc (const char *name) { /* Create a new decl, so that it can be passed to targetm.encode_section_info. */ - /* ??? We don't have any type information except for this is - a function. Pretend this is "int foo()". */ - decl = build_decl (UNKNOWN_LOCATION, - FUNCTION_DECL, get_identifier (name), - build_function_type (integer_type_node, NULL_TREE)); - DECL_ARTIFICIAL (decl) = 1; - DECL_EXTERNAL (decl) = 1; - TREE_PUBLIC (decl) = 1; - - /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with - are the flags assigned by targetm.encode_section_info. */ - SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL); - + decl = build_libfunc_function (name); *slot = decl; } return XEXP (DECL_RTL (decl), 0); diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index d9baf71..ac87f42 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -1939,6 +1939,14 @@ lower_eh_constructs (void) htab_delete (finally_tree); collect_eh_region_array (); + + /* If this function needs a language specific EH personality routine + and the frontend didn't already set one do so now. */ + if (function_needs_eh_personality (cfun) == eh_personality_lang + && !DECL_FUNCTION_PERSONALITY (current_function_decl)) + DECL_FUNCTION_PERSONALITY (current_function_decl) + = lang_hooks.eh_personality (); + return 0; } diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index b5e7346..b83c52f 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -3505,6 +3505,13 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) cg_edge = cgraph_edge (id->dst_node, stmt); + /* Don't inline functions with different EH personalities. */ + if (DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl) + && DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl) + && (DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl) + != DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl))) + goto egress; + /* Don't try to inline functions that are not well-suited to inlining. */ if (!cgraph_inline_p (cg_edge, &reason)) @@ -3546,6 +3553,11 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) /* We will be inlining this callee. */ id->eh_region = lookup_stmt_eh_region (stmt); + /* Update the callers EH personality. */ + if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl)) + DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl) + = DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl); + /* Split the block holding the GIMPLE_CALL. */ e = split_block (bb, stmt); bb = e->src; @@ -4730,6 +4742,7 @@ tree_function_versioning (tree old_decl, tree new_decl, DECL_ARTIFICIAL (new_decl) = 1; DECL_ABSTRACT_ORIGIN (new_decl) = DECL_ORIGIN (old_decl); + DECL_FUNCTION_PERSONALITY (new_decl) = DECL_FUNCTION_PERSONALITY (old_decl); /* Prepare the data structures for the tree copy. */ memset (&id, 0, sizeof (id)); @@ -5000,6 +5013,18 @@ tree_can_inline_p (struct cgraph_edge *e) caller = e->caller->decl; callee = e->callee->decl; + /* We cannot inline a function that uses a different EH personality + than the caller. */ + if (DECL_FUNCTION_PERSONALITY (caller) + && DECL_FUNCTION_PERSONALITY (callee) + && (DECL_FUNCTION_PERSONALITY (caller) + != DECL_FUNCTION_PERSONALITY (callee))) + { + e->inline_failed = CIF_UNSPECIFIED; + gimple_call_set_cannot_inline (e->call_stmt, true); + return false; + } + /* Allow the backend to decide if inlining is ok. */ if (!targetm.target_option.can_inline_p (caller, callee)) { @@ -10566,5 +10566,20 @@ tree_strip_sign_nop_conversions (tree exp) return exp; } +static GTY(()) tree gcc_eh_personality_decl; + +/* Return the GCC personality function decl. */ + +tree +lhd_gcc_personality (void) +{ + if (!gcc_eh_personality_decl) + gcc_eh_personality_decl + = build_personality_function (USING_SJLJ_EXCEPTIONS + ? "__gcc_personality_sj0" + : "__gcc_personality_v0"); + + return gcc_eh_personality_decl; +} #include "gt-tree.h" @@ -2538,6 +2538,9 @@ struct GTY(()) tree_decl_minimal { #define DECL_DEBUG_EXPR_IS_FROM(NODE) \ (DECL_COMMON_CHECK (NODE)->decl_common.debug_expr_is_from) +#define DECL_FUNCTION_PERSONALITY(NODE) \ + (FUNCTION_DECL_CHECK (NODE)->function_decl.personality) + /* Nonzero for a given ..._DECL node means that the name of this node should be ignored for symbolic debug purposes. Moreover, for a FUNCTION_DECL, the body of the function should also be ignored. */ @@ -3191,6 +3194,9 @@ struct GTY(()) tree_function_decl { struct function *f; + /* The personality function. Used for stack unwinding. */ + tree personality; + /* Function specific options that are used by this function. */ tree function_specific_target; /* target options */ tree function_specific_optimization; /* optimization options */ @@ -4653,6 +4659,7 @@ extern bool auto_var_in_fn_p (const_tree, const_tree); extern tree build_low_bits_mask (tree, unsigned); extern tree tree_strip_nop_conversions (tree); extern tree tree_strip_sign_nop_conversions (tree); +extern tree lhd_gcc_personality (void); /* In cgraph.c */ extern void change_decl_assembler_name (tree, tree); @@ -5264,6 +5271,7 @@ extern unsigned HOST_WIDE_INT compute_builtin_object_size (tree, int); /* In expr.c. */ extern unsigned HOST_WIDE_INT highest_pow2_factor (const_tree); +extern tree build_personality_function (const char *); /* In tree-inline.c. */ |