Commit db4283a0 by Mark Mitchell Committed by Mark Mitchell

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
parent fc693822
1999-12-16 Mark Mitchell <mark@codesourcery.com> 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. * class.c (check_field_decls): Don't return a value.
(avoid_overlap): Moved here from tree.c. (avoid_overlap): Moved here from tree.c.
(build_base_fields): Likewise. (build_base_fields): Likewise.
......
...@@ -483,6 +483,7 @@ enum cp_tree_index ...@@ -483,6 +483,7 @@ enum cp_tree_index
CPTI_MINUS_ONE, CPTI_MINUS_ONE,
CPTI_TERMINATE, CPTI_TERMINATE,
CPTI_ATEXIT, CPTI_ATEXIT,
CPTI_DSO_HANDLE,
CPTI_MAX CPTI_MAX
}; };
...@@ -574,9 +575,12 @@ extern tree cp_global_trees[CPTI_MAX]; ...@@ -574,9 +575,12 @@ extern tree cp_global_trees[CPTI_MAX];
/* The declaration for `std::terminate'. */ /* The declaration for `std::terminate'. */
#define terminate_node cp_global_trees[CPTI_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] #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. */ /* The type of a destructor. */
#define cleanup_type cp_global_trees[CPTI_CLEANUP_TYPE] #define cleanup_type cp_global_trees[CPTI_CLEANUP_TYPE]
...@@ -3128,6 +3132,11 @@ extern int flag_weak; ...@@ -3128,6 +3132,11 @@ extern int flag_weak;
extern int flag_new_abi; 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. */ /* Nonzero to not ignore namespace std. */
extern int flag_honor_std; extern int flag_honor_std;
...@@ -3564,6 +3573,7 @@ extern tree build_target_expr_with_type PROTO((tree, tree)); ...@@ -3564,6 +3573,7 @@ extern tree build_target_expr_with_type PROTO((tree, tree));
extern void make_rtl_for_local_static PROTO((tree)); extern void make_rtl_for_local_static PROTO((tree));
extern int local_variable_p PROTO((tree)); extern int local_variable_p PROTO((tree));
extern int nonstatic_local_decl_p PROTO((tree)); extern int nonstatic_local_decl_p PROTO((tree));
extern tree declare_global_var PROTO((tree, tree));
/* in decl2.c */ /* in decl2.c */
extern void init_decl2 PROTO((void)); extern void init_decl2 PROTO((void));
...@@ -3659,8 +3669,6 @@ extern void expand_builtin_throw PROTO((void)); ...@@ -3659,8 +3669,6 @@ extern void expand_builtin_throw PROTO((void));
extern tree expand_start_eh_spec PROTO((void)); extern tree expand_start_eh_spec PROTO((void));
extern void expand_end_eh_spec PROTO((tree, tree)); extern void expand_end_eh_spec PROTO((tree, tree));
extern void expand_exception_blocks PROTO((void)); 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 tree build_throw PROTO((tree));
extern void mark_all_runtime_matches PROTO((void)); extern void mark_all_runtime_matches PROTO((void));
......
...@@ -175,6 +175,10 @@ static void destroy_local_var PROTO((tree)); ...@@ -175,6 +175,10 @@ static void destroy_local_var PROTO((tree));
static void finish_constructor_body PROTO((void)); static void finish_constructor_body PROTO((void));
static void finish_destructor_body PROTO((void)); static void finish_destructor_body PROTO((void));
static tree create_array_type_for_decl PROTO((tree, tree, tree)); 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) #if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void)); static void indent PROTO((void));
...@@ -7856,6 +7860,184 @@ finish_decl (decl, init, asmspec_tree) ...@@ -7856,6 +7860,184 @@ finish_decl (decl, init, asmspec_tree)
cp_finish_decl (decl, init, asmspec_tree, 0); 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 /* Generate code to handle the destruction of the function-scoped
static variable DECL. */ static variable DECL. */
...@@ -7863,40 +8045,20 @@ static void ...@@ -7863,40 +8045,20 @@ static void
destroy_local_static (decl) destroy_local_static (decl)
tree decl; tree decl;
{ {
tree cleanup, fcall; tree cleanup;
tree compound_stmt; tree compound_stmt;
int saved_flag_access_control; tree args;
tree fcall;
if (atexit_node == 0) int saved_flag_access_control;
{
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);
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 /* Call build_cleanup before we enter the anonymous function so that
any access checks will be done relative to the current scope, any access checks will be done relative to the current scope,
rather than the scope of the anonymous function. */ rather than the scope of the anonymous function. */
build_cleanup (decl); build_cleanup (decl);
/* Now start the function. */ /* Now start the function. */
cleanup = start_anon_func (); cleanup = start_cleanup_fn ();
/* Now, recompute the cleanup. It may contain SAVE_EXPRs that refer /* Now, recompute the cleanup. It may contain SAVE_EXPRs that refer
to the original function, rather than the anonymous one. That to the original function, rather than the anonymous one. That
...@@ -7911,16 +8073,20 @@ destroy_local_static (decl) ...@@ -7911,16 +8073,20 @@ destroy_local_static (decl)
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
finish_expr_stmt (fcall); finish_expr_stmt (fcall);
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
end_anon_func (); end_cleanup_fn ();
/* Call atexit with the cleanup function. */ /* Call atexit with the cleanup function. */
mark_addressable (cleanup); mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0); cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
fcall = build_function_call (atexit_node, if (flag_use_cxa_atexit)
tree_cons (NULL_TREE, {
cleanup, args = tree_cons (NULL_TREE, get_dso_handle_node (), NULL_TREE);
NULL_TREE)); args = tree_cons (NULL_TREE, null_pointer_node, args);
finish_expr_stmt (fcall); 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 void
......
...@@ -441,6 +441,11 @@ int flag_weak = 1; ...@@ -441,6 +441,11 @@ int flag_weak = 1;
int flag_new_abi; 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. */ /* Nonzero to not ignore namespace std. */
int flag_honor_std; int flag_honor_std;
...@@ -535,6 +540,7 @@ lang_f_options[] = ...@@ -535,6 +540,7 @@ lang_f_options[] =
{"squangle", &flag_do_squangling, 1}, {"squangle", &flag_do_squangling, 1},
{"stats", &flag_detailed_statistics, 1}, {"stats", &flag_detailed_statistics, 1},
{"strict-prototype", &flag_strict_prototype, 1}, {"strict-prototype", &flag_strict_prototype, 1},
{"use-cxa-atexit", &flag_use_cxa_atexit, 1},
{"vtable-gc", &flag_vtable_gc, 1}, {"vtable-gc", &flag_vtable_gc, 1},
{"vtable-thunks", &flag_vtable_thunks, 1}, {"vtable-thunks", &flag_vtable_thunks, 1},
{"weak", &flag_weak, 1}, {"weak", &flag_weak, 1},
......
...@@ -681,49 +681,6 @@ expand_exception_blocks () ...@@ -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. */ /* Return a pointer to a buffer for an exception object of type TYPE. */
static tree static tree
......
...@@ -98,6 +98,8 @@ DEFINE_LANG_NAME ("C++") ...@@ -98,6 +98,8 @@ DEFINE_LANG_NAME ("C++")
{ "-ftemplate-depth-", "Specify maximum template instantiation depth"}, { "-ftemplate-depth-", "Specify maximum template instantiation depth"},
{ "-fthis-is-variable", "Make 'this' not be type '* const'" }, { "-fthis-is-variable", "Make 'this' not be type '* const'" },
{ "-fno-this-is-variable", "" }, { "-fno-this-is-variable", "" },
{ "-fuse-cxa-atexit", "Use __cxa_atexit to register destructors." },
{ "-fno-use-cxa-atexit", "" },
{ "-fvtable-gc", "Discard unused virtual functions" }, { "-fvtable-gc", "Discard unused virtual functions" },
{ "-fno-vtable-gc", "" }, { "-fno-vtable-gc", "" },
{ "-fvtable-thunks", "Implement vtables using thunks" }, { "-fvtable-thunks", "Implement vtables using thunks" },
......
...@@ -308,7 +308,7 @@ get_tinfo_var (type) ...@@ -308,7 +308,7 @@ get_tinfo_var (type)
tree type; tree type;
{ {
tree tname = build_overload_with_type (get_identifier ("__ti"), type); tree tname = build_overload_with_type (get_identifier ("__ti"), type);
tree tdecl, arrtype; tree arrtype;
int size; int size;
if (IDENTIFIER_GLOBAL_VALUE (tname)) if (IDENTIFIER_GLOBAL_VALUE (tname))
...@@ -342,16 +342,7 @@ get_tinfo_var (type) ...@@ -342,16 +342,7 @@ get_tinfo_var (type)
(unsigned_char_type_node, (unsigned_char_type_node,
build_index_type (size_int (size / BITS_PER_UNIT - 1))); build_index_type (size_int (size / BITS_PER_UNIT - 1)));
tdecl = build_decl (VAR_DECL, tname, arrtype); return declare_global_var (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;
} }
/* Returns the decl for a function which will return a type_info node for /* Returns the decl for a function which will return a type_info node for
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment