From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8303 invoked by alias); 10 Sep 2009 13:12:08 -0000 Received: (qmail 8207 invoked by uid 22791); 10 Sep 2009 13:12:01 -0000 X-SWARE-Spam-Status: No, hits=-2.9 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN X-Spam-Check-By: sourceware.org Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 10 Sep 2009 13:11:51 +0000 Received: from relay2.suse.de (relay-ext.suse.de [195.135.221.8]) by mx2.suse.de (Postfix) with ESMTP id 083FF86445; Thu, 10 Sep 2009 15:11:48 +0200 (CEST) Date: Thu, 10 Sep 2009 13:12:00 -0000 From: Richard Guenther To: Richard Henderson Cc: gcc-patches@gcc.gnu.org, Diego Novillo Subject: Re: [PATCH] Merge from LTO: eh_personality changes In-Reply-To: <4AA67D0C.8000704@redhat.com> Message-ID: References: <4AA293E4.8090301@redhat.com> <4AA2A9D7.3030406@redhat.com> <4AA67D0C.8000704@redhat.com> User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2009-09/txt/msg00681.txt.bz2 On Tue, 8 Sep 2009, Richard Henderson wrote: > On 09/08/2009 08:20 AM, Richard Guenther wrote: > > > Ok. I'll modify the patch to make this a true langhook and maybe move > > > the eh-personality also to a langhook called from eh lowering. > > > > The latter is difficult as C++ is playing some tricks with Java vs. > > non-Java personality, so I leave that alone for now. > > Ew. > > > FYI the following two patches would implement the above (untested). > > Looks good. I've been playing a bit with optimizing setting of DECL_FUNCTION_EH_PERSONALITY only if the function uses EH types instead of just checking for an empty EH region tree. It doesn't look like its very simple - even a catch (...) needs a personality routine. So I am now testing the following - the ERT_ALLOWED_EXCEPTIONS case is required to get diagnostics from g++.dg/torture/pr34850.C which requires inlining memset into clear_mem. If that doesn't work out I'll refrain from optimizing at all and just disable cross different EH personality TU inlining completely (that already passed bootstrapping and testing, it would be - if (function_needs_eh_personality (cfun)) - DECL_FUNCTION_PERSONALITY (current_function_decl) = eh_personality_decl; + DECL_FUNCTION_PERSONALITY (current_function_decl) = eh_personality_decl; meaning no functional change as far as trunk is concerned) Ok for trunk if bootstrapping and testing succeeds? Thanks, Richard. 2009-09-10 Richard Guenther Rafael Avila de Espindola * langhooks-def.h (LANG_HOOKS_INIT_EH): Define. (LANG_HOOKS_EH_RUNTIME_TYPE): Likewise. (LANG_HOOKS_INITIALIZER): Adjust. (lhd_pass_through_t): Declare. * langhooks.h (struct lang_hooks): Add init_eh and eh_runtime_type. * 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 (build_personality_function): Declare. (get_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. * toplev.c (eh_personality_decl): New. * tree.h (DECL_FUNCTION_PERSONALITY): New. (tree_function_decl): Add personality. (eh_personality_decl): New. * except.h (lang_eh_runtime_type): Remove. (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. * c-lang.c (LANG_HOOKS_INIT_EH): Define. * c-tree.h (c_eh_initialized_p): Remove. * c-decl.c (finish_decl): Don't call c_maybe_initialize_eh. Init eh_personality_decl instead of eh_personality_libfunc. (finish_decl): Don't call c_maybe_initialize_eh. (c_eh_initialized_p): Make local to ... (c_maybe_initialize_eh): ... this function. Init eh_personality_decl instead of eh_personality_libfunc. * c-parser.c (c_parser_omp_construct): Likewise. (c_parse_file): Call lang_hooks.init_eh. objc/ * objc-act.c (objc_eh_runtime_type): Export. (objc_init_exceptions): Export. Init eh_personality_decl instead of eh_personality_libfunc. Do not set objc_init_exceptions. Move warning code ... (objc_begin_try_stmt): ... here (objc_build_throw_stmt): ... and here. * objc-act.h (objc_init_exceptions): Declare. (objc_eh_runtime_type): Likewise. * objc-lang.c (LANG_HOOKS_INIT_EH): Define. (LANG_HOOKS_EH_RUNTIME_TYPE): Likewise. cp/ * except.c (init_exception_processing): Do not set lang_eh_runtime_type. Init eh_personality_decl instead of eh_personality_libfunc. * cp-lang.c (LANG_HOOKS_EH_RUNTIME_TYPE): Define. java/ * decl.c (do_nothing): Remove. (java_init_decl_processing): Do not set lang_eh_runtime_type. Init eh_personality_decl instead of eh_personality_libfunc. ada/ * gcc-interface/misc.c (gnat_init_gcc_eh): Do not set lang_eh_runtime_type. Init eh_personality_decl instead of eh_personality_libfunc. fortran/ * f95-lang.c (gfc_maybe_initialize_eh): Init eh_personality_decl instead of eh_personality_libfunc. Index: gcc/objc/objc-act.c =================================================================== *** gcc/objc/objc-act.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/objc/objc-act.c 2009-09-10 14:18:42.000000000 +0200 *************** static struct objc_try_context *cur_try_ *** 3488,3494 **** /* ??? Isn't there a class object or some such? Is it easy to get? */ #ifndef OBJCPLUS ! static tree objc_eh_runtime_type (tree type) { return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names); --- 3488,3494 ---- /* ??? Isn't there a class object or some such? Is it easy to get? */ #ifndef OBJCPLUS ! tree objc_eh_runtime_type (tree type) { return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names); *************** objc_eh_runtime_type (tree type) *** 3497,3503 **** /* Initialize exception handling. */ ! static void objc_init_exceptions (void) { static bool done = false; --- 3497,3503 ---- /* Initialize exception handling. */ ! void objc_init_exceptions (void) { static bool done = false; *************** objc_init_exceptions (void) *** 3505,3529 **** return; done = true; - 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 } --- 3505,3519 ---- return; done = true; #ifndef OBJCPLUS ! if (!flag_objc_sjlj_exceptions) { ! eh_personality_decl ! = build_personality_function (USING_SJLJ_EXCEPTIONS ! ? "__gnu_objc_personality_sj0" ! : "__gnu_objc_personality_v0"); default_init_unwind_resume_libfunc (); using_eh_for_cleanups (); } #endif } *************** objc_begin_try_stmt (location_t try_locu *** 3824,3830 **** c->end_try_locus = input_location; cur_try_context = c; ! objc_init_exceptions (); if (flag_objc_sjlj_exceptions) objc_mark_locals_volatile (NULL); --- 3814,3827 ---- c->end_try_locus = input_location; cur_try_context = c; ! 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); *************** objc_build_throw_stmt (location_t loc, t *** 3973,3979 **** { tree args; ! objc_init_exceptions (); if (throw_expr == NULL) { --- 3970,3983 ---- { tree args; ! 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) { Index: gcc/c-decl.c =================================================================== *** gcc/c-decl.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/c-decl.c 2009-09-10 14:18:42.000000000 +0200 *************** tree pending_invalid_xref; *** 92,100 **** /* 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. */ --- 92,97 ---- *************** merge_decls (tree newdecl, tree olddecl, *** 2365,2371 **** TREE_USED (olddecl) = 1; /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. ! But preserve OLDDECL's DECL_UID and DECL_CONTEXT. */ { unsigned olddecl_uid = DECL_UID (olddecl); tree olddecl_context = DECL_CONTEXT (olddecl); --- 2362,2369 ---- TREE_USED (olddecl) = 1; /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. ! 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); *************** start_decl (struct c_declarator *declara *** 4048,4061 **** 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 (); } --- 4046,4062 ---- void c_maybe_initialize_eh (void) { + static bool c_eh_initialized_p = false; + if (!flag_exceptions || c_eh_initialized_p) return; c_eh_initialized_p = true; ! eh_personality_decl ! = build_personality_function (USING_SJLJ_EXCEPTIONS ! ? "__gcc_personality_sj0" ! : "__gcc_personality_v0"); ! default_init_unwind_resume_libfunc (); using_eh_for_cleanups (); } *************** finish_decl (tree decl, location_t init_ *** 4360,4368 **** 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); } } --- 4361,4366 ---- Index: gcc/c-parser.c =================================================================== *** gcc/c-parser.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/c-parser.c 2009-09-10 14:18:42.000000000 +0200 *************** c_parser_omp_construct (c_parser *parser *** 8489,8500 **** 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: --- 8489,8494 ---- *************** c_parse_file (void) *** 8607,8612 **** --- 8601,8609 ---- the_parser = GGC_NEW (c_parser); *the_parser = tparser; + /* Initialize EH, if we've been told to do so. */ + lang_hooks.init_eh (); + c_parser_translation_unit (the_parser); the_parser = NULL; } Index: gcc/c-lang.c =================================================================== *** gcc/c-lang.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/c-lang.c 2009-09-10 14:18:42.000000000 +0200 *************** enum c_language_kind c_language = clk_c; *** 44,49 **** --- 44,51 ---- #define LANG_HOOKS_NAME "GNU C" #undef LANG_HOOKS_INIT #define LANG_HOOKS_INIT c_objc_common_init + #undef LANG_HOOKS_INIT_EH + #define LANG_HOOKS_INIT_EH c_maybe_initialize_eh /* Each front end provides its own lang hook initializer. */ struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; Index: gcc/langhooks-def.h =================================================================== *** gcc/langhooks-def.h.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/langhooks-def.h 2009-09-10 14:18:42.000000000 +0200 *************** extern void lhd_do_nothing (void); *** 40,45 **** --- 40,46 ---- 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); *************** extern void lhd_omp_firstprivatize_type_ *** 107,112 **** --- 108,115 ---- #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_INIT_EH NULL + #define LANG_HOOKS_EH_RUNTIME_TYPE lhd_pass_through_t /* Attribute hooks. */ #define LANG_HOOKS_ATTRIBUTE_TABLE NULL *************** extern tree lhd_make_node (enum tree_cod *** 271,276 **** --- 274,281 ---- LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \ LANG_HOOKS_INIT_TS, \ LANG_HOOKS_EXPR_TO_DECL, \ + LANG_HOOKS_INIT_EH, \ + LANG_HOOKS_EH_RUNTIME_TYPE, \ } #endif /* GCC_LANG_HOOKS_DEF_H */ Index: gcc/langhooks.h =================================================================== *** gcc/langhooks.h.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/langhooks.h 2009-09-10 14:18:42.000000000 +0200 *************** struct lang_hooks *** 414,419 **** --- 414,425 ---- if in the process TREE_CONSTANT or TREE_SIDE_EFFECTS need updating. */ tree (*expr_to_decl) (tree expr, bool *tc, bool *se); + /* Called to initialize the exception handing personality. */ + void (*init_eh) (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. */ }; Index: gcc/objc/objc-act.h =================================================================== *** gcc/objc/objc-act.h.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/objc/objc-act.h 2009-09-10 14:18:42.000000000 +0200 *************** const char *objc_printable_name (tree, i *** 32,37 **** --- 32,39 ---- void objc_finish_file (void); tree objc_fold_obj_type_ref (tree, tree); int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *); + void objc_init_exceptions (void); + tree objc_eh_runtime_type (tree); /* NB: The remaining public functions are prototyped in c-common.h, for the benefit of stub-objc.c and objc-act.c. */ Index: gcc/objc/objc-lang.c =================================================================== *** gcc/objc/objc-lang.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/objc/objc-lang.c 2009-09-10 14:18:42.000000000 +0200 *************** static void objc_init_ts (void); *** 50,55 **** --- 50,62 ---- #define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr #undef LANG_HOOKS_INIT_TS #define LANG_HOOKS_INIT_TS objc_init_ts + #undef LANG_HOOKS_INIT_EH + #define LANG_HOOKS_INIT_EH objc_init_exceptions + + #ifndef OBJCPLUS + #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; Index: gcc/ada/gcc-interface/misc.c =================================================================== *** gcc/ada/gcc-interface/misc.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/ada/gcc-interface/misc.c 2009-09-10 14:18:42.000000000 +0200 *************** gnat_init_gcc_eh (void) *** 431,441 **** 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 --- 431,442 ---- right exception regions. */ using_eh_for_cleanups (); ! eh_personality_decl ! = build_personality_function (USING_SJLJ_EXCEPTIONS ! ? "__gnat_eh_personality_sj" ! : "__gnat_eh_personality"); ! lang_eh_type_covers = gnat_eh_type_covers; default_init_unwind_resume_libfunc (); /* Turn on -fexceptions and -fnon-call-exceptions. The first one triggers Index: gcc/cp/cp-lang.c =================================================================== *** gcc/cp/cp-lang.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/cp/cp-lang.c 2009-09-10 14:18:42.000000000 +0200 *************** static enum classify_record cp_classify_ *** 71,76 **** --- 71,78 ---- #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_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; Index: gcc/cp/except.c =================================================================== *** gcc/cp/except.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/cp/except.c 2009-09-10 14:18:42.000000000 +0200 *************** along with GCC; see the file COPYING3. *** 43,49 **** 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); --- 43,48 ---- *************** init_exception_processing (void) *** 78,92 **** 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; } --- 77,92 ---- call_unexpected_node = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp); ! eh_personality_decl ! = build_personality_function (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_protect_cleanup_actions = &cp_protect_cleanup_actions; } *************** eh_type_info (tree type) *** 143,149 **** /* Build the address of a typeinfo decl for use in the runtime matching field of the exception model. */ ! static tree build_eh_type_type (tree type) { tree exp = eh_type_info (type); --- 143,149 ---- /* Build the address of a typeinfo decl for use in the runtime matching field of the exception model. */ ! tree build_eh_type_type (tree type) { tree exp = eh_type_info (type); *************** decl_is_java_type (tree decl, int err) *** 313,319 **** /* 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 __gxx_personality_(sj|v)0 in init_exception_processing - should it be done here instead? */ void --- 313,319 ---- /* 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_decl is set to __gxx_personality_(sj|v)0 in init_exception_processing - should it be done here instead? */ void *************** choose_personality_routine (enum languag *** 354,362 **** 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"); break; default: --- 354,363 ---- case lang_java: state = chose_java; terminate_node = built_in_decls [BUILT_IN_ABORT]; ! eh_personality_decl ! = build_personality_function (USING_SJLJ_EXCEPTIONS ! ? "__gcj_personality_sj0" ! : "__gcj_personality_v0"); break; default: Index: gcc/except.c =================================================================== *** gcc/except.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/except.c 2009-09-10 14:57:22.000000000 +0200 *************** gimple (*lang_protect_cleanup_actions) ( *** 92,100 **** /* 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 { --- 92,97 ---- *************** add_type_for_runtime (tree type) *** 1696,1702 **** TREE_HASH (type), INSERT); if (*slot == NULL) { ! tree runtime = (*lang_eh_runtime_type) (type); *slot = tree_cons (type, runtime, NULL_TREE); } } --- 1693,1699 ---- TREE_HASH (type), INSERT); if (*slot == NULL) { ! tree runtime = lang_hooks.eh_runtime_type (type); *slot = tree_cons (type, runtime, NULL_TREE); } } *************** sjlj_emit_function_enter (rtx dispatch_l *** 2424,2429 **** --- 2421,2427 ---- { rtx fn_begin, fc, mem, seq; bool fn_begin_outside_block; + rtx personality = get_personality_function (current_function_decl); fc = crtl->eh.sjlj_fc; *************** sjlj_emit_function_enter (rtx dispatch_l *** 2432,2440 **** /* 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); mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs); ! emit_move_insn (mem, eh_personality_libfunc); mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs); if (crtl->uses_eh_lsda) --- 2430,2438 ---- /* 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 (personality); mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs); ! emit_move_insn (mem, personality); mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs); if (crtl->uses_eh_lsda) *************** output_ttype (tree type, int tt_format, *** 4394,4400 **** static void output_one_function_exception_table (const char * ARG_UNUSED (fnname), ! int section) { int tt_format, cs_format, lp_format, i, n; #ifdef HAVE_AS_LEB128 --- 4392,4398 ---- static void output_one_function_exception_table (const char * ARG_UNUSED (fnname), ! int section, rtx ARG_UNUSED (personality)) { int tt_format, cs_format, lp_format, i, n; #ifdef HAVE_AS_LEB128 *************** output_one_function_exception_table (con *** 4410,4416 **** #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); 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. */ --- 4408,4414 ---- #ifdef TARGET_UNWIND_INFO /* TODO: Move this into target file. */ fputs ("\t.personality\t", asm_out_file); ! 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. */ *************** output_one_function_exception_table (con *** 4580,4595 **** void output_function_exception_table (const char * ARG_UNUSED (fnname)) { /* Not all functions need anything. */ if (! crtl->uses_eh_lsda) return; ! if (eh_personality_libfunc) ! assemble_external_libcall (eh_personality_libfunc); ! output_one_function_exception_table (fnname, 0); if (crtl->eh.call_site_record[1] != NULL) ! output_one_function_exception_table (fnname, 1); switch_to_section (current_function_section ()); } --- 4578,4595 ---- 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 (personality) ! assemble_external_libcall (personality); ! output_one_function_exception_table (fnname, 0, personality); if (crtl->eh.call_site_record[1] != NULL) ! output_one_function_exception_table (fnname, 1, personality); switch_to_section (current_function_section ()); } *************** get_eh_throw_stmt_table (struct function *** 4606,4611 **** --- 4606,4662 ---- return fun->eh->throw_stmt_table; } + /* Return true if the function deeds a EH personality function. */ + + bool + function_needs_eh_personality (struct function *fn) + { + struct eh_region_d *i; + int depth = 0; + + i = fn->eh->region_tree; + if (!i) + return false; + + while (1) + { + switch (i->type) + { + case ERT_CATCH: + return true; + + case ERT_ALLOWED_EXCEPTIONS: + if (i->u.allowed.type_list) + return true; + break; + + default: + break; + } + /* 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 false; + } + while (i->next_peer == NULL); + i = i->next_peer; + } + } + + return false; + } + /* Dump EH information to OUT. */ void Index: gcc/except.h =================================================================== *** gcc/except.h.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/except.h 2009-09-10 14:50:26.000000000 +0200 *************** extern gimple (*lang_protect_cleanup_act *** 217,225 **** /* 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 --- 217,222 ---- *************** extern int num_eh_regions (void); *** 277,279 **** --- 274,277 ---- 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); + extern bool function_needs_eh_personality (struct function *); Index: gcc/java/decl.c =================================================================== *** gcc/java/decl.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/java/decl.c 2009-09-10 14:18:42.000000000 +0200 *************** create_primitive_vtable (const char *nam *** 510,521 **** 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) --- 510,515 ---- *************** java_init_decl_processing (void) *** 1195,1210 **** 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]; --- 1189,1205 ---- 0, NOT_BUILT_IN, NULL, NULL_TREE); /* Initialize variables for except.c. */ ! ! eh_personality_decl ! = build_personality_function (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 (); initialize_builtins (); soft_fmod_node = built_in_decls[BUILT_IN_FMOD]; Index: gcc/langhooks.c =================================================================== *** gcc/langhooks.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/langhooks.c 2009-09-10 14:18:42.000000000 +0200 *************** lhd_do_nothing_t (tree ARG_UNUSED (t)) *** 53,58 **** --- 53,65 ---- { } + /* Pass through (tree). */ + tree + lhd_pass_through_t (tree t) + { + return t; + } + /* Do nothing (int). */ void Index: gcc/cp/cp-tree.h =================================================================== *** gcc/cp/cp-tree.h.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/cp/cp-tree.h 2009-09-10 14:18:42.000000000 +0200 *************** extern void choose_personality_routine *** 4521,4526 **** --- 4521,4527 ---- 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); Index: gcc/libfuncs.h =================================================================== *** gcc/libfuncs.h.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/libfuncs.h 2009-09-10 14:18:42.000000000 +0200 *************** enum libfunc_index *** 31,37 **** LTI_setbits, LTI_unwind_resume, - LTI_eh_personality, LTI_setjmp, LTI_longjmp, LTI_unwind_sjlj_register, --- 31,36 ---- *************** extern GTY(()) rtx libfunc_table[LTI_MAX *** 61,67 **** #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]) --- 60,65 ---- Index: gcc/optabs.c =================================================================== *** gcc/optabs.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/optabs.c 2009-09-10 14:18:42.000000000 +0200 *************** libfunc_decl_eq (const void *entry1, con *** 6023,6028 **** --- 6023,6050 ---- 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) { *************** init_one_libfunc (const char *name) *** 6043,6061 **** { /* 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); ! *slot = decl; } return XEXP (DECL_RTL (decl), 0); --- 6065,6071 ---- { /* Create a new decl, so that it can be passed to targetm.encode_section_info. */ ! decl = build_libfunc_function (name); *slot = decl; } return XEXP (DECL_RTL (decl), 0); Index: gcc/tree.h =================================================================== *** gcc/tree.h.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/tree.h 2009-09-10 14:18:42.000000000 +0200 *************** struct GTY(()) tree_decl_minimal { *** 2538,2543 **** --- 2538,2546 ---- #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. */ #define DECL_IGNORED_P(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.ignored_flag) *************** struct GTY(()) tree_function_decl { *** 3188,3193 **** --- 3191,3199 ---- 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 */ *************** extern int pedantic_lvalues; *** 4557,4562 **** --- 4563,4571 ---- extern GTY(()) tree current_function_decl; + /* The eh personally function that this FE wants to use. */ + extern GTY(()) tree eh_personality_decl; + /* Nonzero means a FUNC_BEGIN label was emitted. */ extern GTY(()) const char * current_function_func_begin_label; Index: gcc/toplev.c =================================================================== *** gcc/toplev.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/toplev.c 2009-09-10 14:18:42.000000000 +0200 *************** int optimize_size = 0; *** 202,207 **** --- 202,210 ---- or 0 if between functions. */ tree current_function_decl; + /* The EH personality function that this FE wants to use. */ + tree eh_personality_decl; + /* Set to the FUNC_BEGIN label of the current function, or NULL if none. */ const char * current_function_func_begin_label; Index: gcc/dwarf2out.c =================================================================== *** gcc/dwarf2out.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/dwarf2out.c 2009-09-10 14:18:42.000000000 +0200 *************** static GTY(()) section *debug_str_sectio *** 216,221 **** --- 216,225 ---- 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 ";#" *************** output_call_frame_info (int for_eh) *** 3599,3604 **** --- 3603,3609 ---- 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. */ *************** output_call_frame_info (int for_eh) *** 3684,3689 **** --- 3689,3696 ---- augmentation[0] = 0; augmentation_size = 0; + + personality = current_unit_personality; if (for_eh) { char *p; *************** output_call_frame_info (int for_eh) *** 3703,3713 **** lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0); p = augmentation + 1; ! if (eh_personality_libfunc) { *p++ = 'P'; augmentation_size += 1 + size_of_encoded_value (per_encoding); ! assemble_external_libcall (eh_personality_libfunc); } if (any_lsda_needed) { --- 3710,3720 ---- lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0); p = augmentation + 1; ! if (personality) { *p++ = 'P'; augmentation_size += 1 + size_of_encoded_value (per_encoding); ! assemble_external_libcall (personality); } if (any_lsda_needed) { *************** output_call_frame_info (int for_eh) *** 3726,3732 **** } /* Ug. Some platforms can't do unaligned dynamic relocations at all. */ ! if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned) { int offset = ( 4 /* Length */ + 4 /* CIE Id */ --- 3733,3739 ---- } /* Ug. Some platforms can't do unaligned dynamic relocations at all. */ ! if (personality && per_encoding == DW_EH_PE_aligned) { int offset = ( 4 /* Length */ + 4 /* CIE Id */ *************** output_call_frame_info (int for_eh) *** 3760,3771 **** if (augmentation[0]) { dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size"); ! if (eh_personality_libfunc) { 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, true, NULL); } --- 3767,3778 ---- if (augmentation[0]) { dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size"); ! 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, ! personality, true, NULL); } *************** dwarf2out_do_cfi_startproc (bool second) *** 3824,3836 **** { int enc; rtx ref; fprintf (asm_out_file, "\t.cfi_startproc\n"); ! if (eh_personality_libfunc) { enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1); ! ref = eh_personality_libfunc; /* ??? The GAS support isn't entirely consistent. We have to handle indirect support ourselves, but PC-relative is done --- 3831,3844 ---- { int enc; rtx ref; + rtx personality = get_personality_function (current_function_decl); fprintf (asm_out_file, "\t.cfi_startproc\n"); ! if (personality) { enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1); ! ref = personality; /* ??? The GAS support isn't entirely consistent. We have to handle indirect support ourselves, but PC-relative is done *************** dwarf2out_begin_prologue (unsigned int l *** 3873,3878 **** --- 3881,3887 ---- char label[MAX_ARTIFICIAL_LABEL_BYTES]; char * dup_label; dw_fde_ref fde; + rtx personality; section *fnsec; current_function_func_begin_label = NULL; *************** dwarf2out_begin_prologue (unsigned int l *** 3967,3974 **** --- 3976,3992 ---- 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 Index: gcc/expr.h =================================================================== *** gcc/expr.h.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/expr.h 2009-09-10 14:18:42.000000000 +0200 *************** extern void init_all_optabs (void); *** 814,819 **** --- 814,845 ---- 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 *); + + /* Build a decl for a personality function named NAME. */ + static inline tree + build_personality_function (const char *name) + { + return build_libfunc_function (name); + } + + /* Extracts the personality function of DECL and returns the corresponding + libfunc. */ + + static inline rtx + get_personality_function (tree decl) + { + tree personality = DECL_FUNCTION_PERSONALITY (decl); + tree name; + if (!personality) + return NULL; + + name = DECL_ASSEMBLER_NAME (personality); + + return init_one_libfunc (IDENTIFIER_POINTER (name)); + } + extern int vector_mode_valid_p (enum machine_mode); #endif /* GCC_EXPR_H */ Index: gcc/fortran/f95-lang.c =================================================================== *** gcc/fortran/f95-lang.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/fortran/f95-lang.c 2009-09-10 14:18:42.000000000 +0200 *************** gfc_maybe_initialize_eh (void) *** 1155,1164 **** 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 (); } --- 1155,1164 ---- return; gfc_eh_initialized_p = true; ! eh_personality_decl ! = build_personality_function (USING_SJLJ_EXCEPTIONS ! ? "__gcc_personality_sj0" ! : "__gcc_personality_v0"); default_init_unwind_resume_libfunc (); using_eh_for_cleanups (); } Index: gcc/c-tree.h =================================================================== *** gcc/c-tree.h.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/c-tree.h 2009-09-10 14:18:42.000000000 +0200 *************** extern int system_header_p; *** 589,597 **** 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); --- 589,594 ---- Index: gcc/tree-eh.c =================================================================== *** gcc/tree-eh.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/tree-eh.c 2009-09-10 14:50:38.000000000 +0200 *************** lower_eh_constructs (void) *** 1939,1944 **** --- 1939,1948 ---- htab_delete (finally_tree); collect_eh_region_array (); + + if (function_needs_eh_personality (cfun)) + DECL_FUNCTION_PERSONALITY (current_function_decl) = eh_personality_decl; + return 0; } Index: gcc/tree-inline.c =================================================================== *** gcc/tree-inline.c.orig 2009-09-10 13:40:45.000000000 +0200 --- gcc/tree-inline.c 2009-09-10 14:21:01.000000000 +0200 *************** tree_can_inline_p (struct cgraph_edge *e *** 4999,5004 **** --- 4999,5019 ---- caller = e->caller->decl; callee = e->callee->decl; + /* We cannot inline a function that uses a different EH personality + than the caller. Restrict inlining functions with either no EH + personality or calls with matching personality in the caller + and callee for now, that will not require personality changes + in the caller. Everything more advanced needs to be taken into + account during the inline plan computation. */ + if (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)) {