diff options
author | Mark Mitchell <mark@codesourcery.com> | 1999-12-17 07:40:08 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1999-12-17 07:40:08 +0000 |
commit | db4283a0747a8598d17fa8d2ca94846354831d0d (patch) | |
tree | baf33a58f78965a95318fce634a68a64f07a3cc4 | |
parent | fc69382254fcf45ced69a604adea5b6123c3c1c8 (diff) | |
download | gcc-db4283a0747a8598d17fa8d2ca94846354831d0d.zip gcc-db4283a0747a8598d17fa8d2ca94846354831d0d.tar.gz gcc-db4283a0747a8598d17fa8d2ca94846354831d0d.tar.bz2 |
cp-tree.h (cp_tree_index): Add CPTI_DSO_HANDLE.
* cp-tree.h (cp_tree_index): Add CPTI_DSO_HANDLE.
(dso_handle_node): New macro.
(flag_use_cxa_atexit): New variable.
(declare_global_var): New function.
(start_anon_func): Remove declaration.
(end_anon_func): Likewise.
* decl.c (get_atexit_node): New function, split out from
destroy_local_static. Handle flag_use_cxa_atexit.
(get_dso_handle_node): Likewise.
(start_cleanup_fn): Renamed from start_anon_func. Moved here from
except.c. Handle flag_use_cxa_atexit.
(end_cleanup_fn): Renamed from end_anon_func. Moved here from
except.c.
(declare_global_var): New variable.
(destroy_local_static): Handle flag_use_cxa_atexit.
* decl2.c (flag_use_cxa_atexit): New variable.
(lang_f_options): Likewise.
* except.c (start_anon_func): Remove.
(end_anon_func): Liekwise.
* lang-options.h: Add -fuse-cxa-atexit and -fno-use-cxa-atexit.
* rtti.c (get_tinfo_var): Use declare_global_var.
From-SVN: r30990
-rw-r--r-- | gcc/cp/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 14 | ||||
-rw-r--r-- | gcc/cp/decl.c | 228 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 6 | ||||
-rw-r--r-- | gcc/cp/except.c | 43 | ||||
-rw-r--r-- | gcc/cp/lang-options.h | 2 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 13 |
7 files changed, 242 insertions, 88 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2fe8bd3..73cfd67 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,29 @@ 1999-12-16 Mark Mitchell <mark@codesourcery.com> + * cp-tree.h (cp_tree_index): Add CPTI_DSO_HANDLE. + (dso_handle_node): New macro. + (flag_use_cxa_atexit): New variable. + (declare_global_var): New function. + (start_anon_func): Remove declaration. + (end_anon_func): Likewise. + * decl.c (get_atexit_node): New function, split out from + destroy_local_static. Handle flag_use_cxa_atexit. + (get_dso_handle_node): Likewise. + (start_cleanup_fn): Renamed from start_anon_func. Moved here from + except.c. Handle flag_use_cxa_atexit. + (end_cleanup_fn): Renamed from end_anon_func. Moved here from + except.c. + (declare_global_var): New variable. + (destroy_local_static): Handle flag_use_cxa_atexit. + * decl2.c (flag_use_cxa_atexit): New variable. + (lang_f_options): Likewise. + * except.c (start_anon_func): Remove. + (end_anon_func): Liekwise. + * lang-options.h: Add -fuse-cxa-atexit and -fno-use-cxa-atexit. + * rtti.c (get_tinfo_var): Use declare_global_var. + +1999-12-16 Mark Mitchell <mark@codesourcery.com> + * class.c (check_field_decls): Don't return a value. (avoid_overlap): Moved here from tree.c. (build_base_fields): Likewise. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0fefc7d..6b22ee9 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -483,6 +483,7 @@ enum cp_tree_index CPTI_MINUS_ONE, CPTI_TERMINATE, CPTI_ATEXIT, + CPTI_DSO_HANDLE, CPTI_MAX }; @@ -574,9 +575,12 @@ extern tree cp_global_trees[CPTI_MAX]; /* The declaration for `std::terminate'. */ #define terminate_node cp_global_trees[CPTI_TERMINATE] -/* The declaration for `std::atexit'. */ +/* A pointer to `std::atexit'. */ #define atexit_node cp_global_trees[CPTI_ATEXIT] +/* A pointer to `__dso_handle'. */ +#define dso_handle_node cp_global_trees[CPTI_DSO_HANDLE] + /* The type of a destructor. */ #define cleanup_type cp_global_trees[CPTI_CLEANUP_TYPE] @@ -3128,6 +3132,11 @@ extern int flag_weak; extern int flag_new_abi; +/* Nonzero to use __cxa_atexit, rather than atexit, to register + destructors for local statics and global objects. */ + +extern int flag_use_cxa_atexit; + /* Nonzero to not ignore namespace std. */ extern int flag_honor_std; @@ -3564,6 +3573,7 @@ extern tree build_target_expr_with_type PROTO((tree, tree)); extern void make_rtl_for_local_static PROTO((tree)); extern int local_variable_p PROTO((tree)); extern int nonstatic_local_decl_p PROTO((tree)); +extern tree declare_global_var PROTO((tree, tree)); /* in decl2.c */ extern void init_decl2 PROTO((void)); @@ -3659,8 +3669,6 @@ extern void expand_builtin_throw PROTO((void)); extern tree expand_start_eh_spec PROTO((void)); extern void expand_end_eh_spec PROTO((tree, tree)); extern void expand_exception_blocks PROTO((void)); -extern tree start_anon_func PROTO((void)); -extern void end_anon_func PROTO((void)); extern tree build_throw PROTO((tree)); extern void mark_all_runtime_matches PROTO((void)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b08f4db..6b240f9 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -175,6 +175,10 @@ static void destroy_local_var PROTO((tree)); static void finish_constructor_body PROTO((void)); static void finish_destructor_body PROTO((void)); static tree create_array_type_for_decl PROTO((tree, tree, tree)); +static tree get_atexit_node PROTO((void)); +static tree get_dso_handle_node PROTO((void)); +static tree start_cleanup_fn PROTO((void)); +static void end_cleanup_fn PROTO((void)); #if defined (DEBUG_CP_BINDING_LEVELS) static void indent PROTO((void)); @@ -7856,6 +7860,184 @@ finish_decl (decl, init, asmspec_tree) cp_finish_decl (decl, init, asmspec_tree, 0); } +/* Returns a declaration for a VAR_DECL as if: + + extern "C" TYPE NAME; + + had been seen. Used to create compiler-generated global + variables. */ + +tree +declare_global_var (name, type) + tree name; + tree type; +{ + tree decl; + + push_to_top_level (); + decl = build_decl (VAR_DECL, name, type); + TREE_PUBLIC (decl) = 1; + DECL_EXTERNAL (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + pushdecl (decl); + cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0); + pop_from_top_level (); + + return decl; +} + +/* Returns a pointer to the `atexit' function. Note that if + FLAG_USE_CXA_ATEXIT is non-zero, then this will actually be the new + `__cxa_atexit' function specified in the IA64 C++ ABI. */ + +static tree +get_atexit_node () +{ + tree atexit_fndecl; + tree arg_types; + tree fn_type; + tree fn_ptr_type; + const char *name; + + if (atexit_node) + return atexit_node; + + if (flag_use_cxa_atexit) + { + /* The declaration for `__cxa_atexit' is: + + int __cxa_atexit (void (*)(void *), void *, void *) + + We build up the argument types and then then function type + itself. */ + + /* First, build the pointer-to-function type for the first + argument. */ + arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + fn_type = build_function_type (void_type_node, arg_types); + fn_ptr_type = build_pointer_type (fn_type); + /* Then, build the rest of the argument types. */ + arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types); + arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types); + /* And the final __cxa_atexit type. */ + fn_type = build_function_type (integer_type_node, arg_types); + fn_ptr_type = build_pointer_type (fn_type); + name = "__cxa_atexit"; + } + else + { + /* The declaration for `atexit' is: + + int atexit (void (*)()); + + We build up the argument types and then then function type + itself. */ + fn_type = build_function_type (void_type_node, void_list_node); + fn_ptr_type = build_pointer_type (fn_type); + arg_types = tree_cons (NULL_TREE, fn_ptr_type, void_list_node); + /* Build the final atexit type. */ + fn_type = build_function_type (integer_type_node, arg_types); + name = "atexit"; + } + + /* Now, build the function declaration. */ + push_lang_context (lang_name_c); + atexit_fndecl = define_function (name, fn_type, /*pfn=*/0, NULL_PTR); + mark_used (atexit_fndecl); + pop_lang_context (); + atexit_node = default_conversion (atexit_fndecl); + + return atexit_node; +} + +/* Returns the __dso_handle VAR_DECL. */ + +static tree +get_dso_handle_node () +{ + if (dso_handle_node) + return dso_handle_node; + + /* Declare the variable. */ + dso_handle_node = declare_global_var (get_identifier ("__dso_handle"), + ptr_type_node); + + return dso_handle_node; +} + +/* Begin a new function with internal linkage whose job will be simply + to destroy some particular variable. */ + +static tree +start_cleanup_fn () +{ + static int counter = 0; + int old_interface_unknown = interface_unknown; + char name[32]; + tree parmtypes; + tree fntype; + tree fndecl; + + push_to_top_level (); + + /* No need to mangle this. */ + push_lang_context (lang_name_c); + + interface_unknown = 1; + + /* Build the parameter-types. */ + parmtypes = void_list_node; + /* Functions passed to __cxa_atexit take an additional parameter. + We'll just ignore it. After we implement the new calling + convention for destructors, we can eliminate the use of + additional cleanup functions entirely in the -fnew-abi case. */ + if (flag_use_cxa_atexit) + parmtypes = tree_cons (NULL_TREE, ptr_type_node, parmtypes); + /* Build the function type itself. */ + fntype = build_function_type (void_type_node, parmtypes); + /* Build the name of the function. */ + sprintf (name, "__tcf_%d", counter++); + /* Build the function declaration. */ + fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype); + /* It's a function with internal linkage, generated by the + compiler. */ + TREE_PUBLIC (fndecl) = 0; + DECL_ARTIFICIAL (fndecl) = 1; + /* Build the parameter. */ + if (flag_use_cxa_atexit) + { + tree parmdecl; + + parmdecl = build_decl (PARM_DECL, NULL_TREE, ptr_type_node); + DECL_CONTEXT (parmdecl) = fndecl; + DECL_ARG_TYPE (parmdecl) = ptr_type_node; + TREE_USED (parmdecl) = 1; + DECL_ARGUMENTS (fndecl) = parmdecl; + } + + start_function (/*specs=*/NULL_TREE, fndecl, NULL_TREE, SF_PRE_PARSED); + do_pushlevel (); + + interface_unknown = old_interface_unknown; + + pop_lang_context (); + + return current_function_decl; +} + +/* Finish the cleanup function begun by start_cleanup_fn. */ + +static void +end_cleanup_fn () +{ + do_poplevel (); + + expand_body (finish_function (lineno, 0)); + + pop_from_top_level (); +} + /* Generate code to handle the destruction of the function-scoped static variable DECL. */ @@ -7863,40 +8045,20 @@ static void destroy_local_static (decl) tree decl; { - tree cleanup, fcall; + tree cleanup; tree compound_stmt; - int saved_flag_access_control; + tree args; + tree fcall; - if (atexit_node == 0) - { - tree atexit_fndecl, PFV, pfvlist; - - PFV = build_pointer_type (build_function_type - (void_type_node, void_list_node)); - - pfvlist = tree_cons (NULL_TREE, PFV, void_list_node); + int saved_flag_access_control; - push_lang_context (lang_name_c); - /* Note that we do not call pushdecl for this function; - there's no reason that this declaration should be - accessible to anyone. */ - atexit_fndecl - = define_function ("atexit", - build_function_type (void_type_node, - pfvlist), - /*pfn=*/0, NULL_PTR); - mark_used (atexit_fndecl); - atexit_node = default_conversion (atexit_fndecl); - pop_lang_context (); - } - /* Call build_cleanup before we enter the anonymous function so that any access checks will be done relative to the current scope, rather than the scope of the anonymous function. */ build_cleanup (decl); /* Now start the function. */ - cleanup = start_anon_func (); + cleanup = start_cleanup_fn (); /* Now, recompute the cleanup. It may contain SAVE_EXPRs that refer to the original function, rather than the anonymous one. That @@ -7911,16 +8073,20 @@ destroy_local_static (decl) compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); finish_expr_stmt (fcall); finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); - end_anon_func (); + end_cleanup_fn (); /* Call atexit with the cleanup function. */ mark_addressable (cleanup); cleanup = build_unary_op (ADDR_EXPR, cleanup, 0); - fcall = build_function_call (atexit_node, - tree_cons (NULL_TREE, - cleanup, - NULL_TREE)); - finish_expr_stmt (fcall); + if (flag_use_cxa_atexit) + { + args = tree_cons (NULL_TREE, get_dso_handle_node (), NULL_TREE); + args = tree_cons (NULL_TREE, null_pointer_node, args); + args = tree_cons (NULL_TREE, cleanup, args); + } + else + args = tree_cons (NULL_TREE, cleanup, NULL_TREE); + finish_expr_stmt (build_function_call (get_atexit_node (), args)); } void diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 937a164..7ed8ab0 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -441,6 +441,11 @@ int flag_weak = 1; int flag_new_abi; +/* Nonzero to use __cxa_atexit, rather than atexit, to register + destructors for local statics and global objects. */ + +int flag_use_cxa_atexit; + /* Nonzero to not ignore namespace std. */ int flag_honor_std; @@ -535,6 +540,7 @@ lang_f_options[] = {"squangle", &flag_do_squangling, 1}, {"stats", &flag_detailed_statistics, 1}, {"strict-prototype", &flag_strict_prototype, 1}, + {"use-cxa-atexit", &flag_use_cxa_atexit, 1}, {"vtable-gc", &flag_vtable_gc, 1}, {"vtable-thunks", &flag_vtable_thunks, 1}, {"weak", &flag_weak, 1}, diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 7e41d2e..1dd167c 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -681,49 +681,6 @@ expand_exception_blocks () } } -tree -start_anon_func () -{ - static int counter = 0; - int old_interface_unknown = interface_unknown; - char name[32]; - tree params; - tree t; - - push_to_top_level (); - - /* No need to mangle this. */ - push_lang_context (lang_name_c); - - interface_unknown = 1; - - params = void_list_node; - /* tcf stands for throw clean function. */ - sprintf (name, "__tcf_%d", counter++); - t = make_call_declarator (get_identifier (name), params, NULL_TREE, - NULL_TREE); - start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"), - void_list_node), - t, NULL_TREE, SF_DEFAULT); - do_pushlevel (); - - interface_unknown = old_interface_unknown; - - pop_lang_context (); - - return current_function_decl; -} - -void -end_anon_func () -{ - do_poplevel (); - - expand_body (finish_function (lineno, 0)); - - pop_from_top_level (); -} - /* Return a pointer to a buffer for an exception object of type TYPE. */ static tree diff --git a/gcc/cp/lang-options.h b/gcc/cp/lang-options.h index 4b743c0..779cbcd 100644 --- a/gcc/cp/lang-options.h +++ b/gcc/cp/lang-options.h @@ -98,6 +98,8 @@ DEFINE_LANG_NAME ("C++") { "-ftemplate-depth-", "Specify maximum template instantiation depth"}, { "-fthis-is-variable", "Make 'this' not be type '* const'" }, { "-fno-this-is-variable", "" }, + { "-fuse-cxa-atexit", "Use __cxa_atexit to register destructors." }, + { "-fno-use-cxa-atexit", "" }, { "-fvtable-gc", "Discard unused virtual functions" }, { "-fno-vtable-gc", "" }, { "-fvtable-thunks", "Implement vtables using thunks" }, diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 6776d11..5c8da91 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -308,7 +308,7 @@ get_tinfo_var (type) tree type; { tree tname = build_overload_with_type (get_identifier ("__ti"), type); - tree tdecl, arrtype; + tree arrtype; int size; if (IDENTIFIER_GLOBAL_VALUE (tname)) @@ -342,16 +342,7 @@ get_tinfo_var (type) (unsigned_char_type_node, build_index_type (size_int (size / BITS_PER_UNIT - 1))); - tdecl = build_decl (VAR_DECL, tname, arrtype); - TREE_PUBLIC (tdecl) = 1; - DECL_EXTERNAL (tdecl) = 1; - DECL_ARTIFICIAL (tdecl) = 1; - push_to_top_level (); - pushdecl (tdecl); - cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0); - pop_from_top_level (); - - return tdecl; + return declare_global_var (tname, arrtype); } /* Returns the decl for a function which will return a type_info node for |