cp-tree.h (struct language_function): Remove temp_name_counter.

* cp-tree.h (struct language_function): Remove temp_name_counter.
	(temp_name_counter): Remove.
	(get_temp_name): Change prototype.
	(get_guard): New function.
	(get_guard_cond): Likewise.
	(set_guard): Likewise.
	* cvt.c (build_up_reference): Adjust call to get_temp_name.
	* decl.c (expand_static_init): Use get_guard and friends to
	implement guard variables.
	* decl2.c (get_temp_name): Assume that the variables created are
	always static.
	(get_sentry): Rename to ...
	(get_guard): ... this.  Implement new ABI guard	variables.
	(get_guard_bits): New function.
	(get_guard_cond): Likewise.
	(set_guard): Likewise.
	(start_static_initialization_or_destruction): Use them.
	(do_static_initialization): Replace sentry with guard throughout.
	(do_static_destruction): Likewise.
	* init.c (create_temporary_var): Add comment.

From-SVN: r34803
This commit is contained in:
Mark Mitchell 2000-06-30 07:16:35 +00:00 committed by Mark Mitchell
parent c1c8f8cc4f
commit c395453cb6
6 changed files with 191 additions and 88 deletions

View File

@ -1,3 +1,26 @@
2000-06-30 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (struct language_function): Remove temp_name_counter.
(temp_name_counter): Remove.
(get_temp_name): Change prototype.
(get_guard): New function.
(get_guard_cond): Likewise.
(set_guard): Likewise.
* cvt.c (build_up_reference): Adjust call to get_temp_name.
* decl.c (expand_static_init): Use get_guard and friends to
implement guard variables.
* decl2.c (get_temp_name): Assume that the variables created are
always static.
(get_sentry): Rename to ...
(get_guard): ... this. Implement new ABI guard variables.
(get_guard_bits): New function.
(get_guard_cond): Likewise.
(set_guard): Likewise.
(start_static_initialization_or_destruction): Use them.
(do_static_initialization): Replace sentry with guard throughout.
(do_static_destruction): Likewise.
* init.c (create_temporary_var): Add comment.
2000-06-29 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (flag_const_strings): Remove.

View File

@ -900,7 +900,6 @@ struct language_function
int returns_value;
int returns_null;
int parms_stored;
int temp_name_counter;
int in_function_try_handler;
int x_expanding_p;
int name_declared;
@ -1004,11 +1003,6 @@ struct language_function
#define vtbls_set_up_p cp_function_chain->vtbls_set_up_p
/* Used to help generate temporary names which are unique within
a function. Reset to 0 by start_function. */
#define temp_name_counter cp_function_chain->temp_name_counter
/* Non-zero if we should generate RTL for functions that we process.
When this is zero, we just accumulate tree structure, without
interacting with the back end. */
@ -4075,7 +4069,7 @@ extern tree constructor_name_full PARAMS ((tree));
extern tree constructor_name PARAMS ((tree));
extern void setup_vtbl_ptr PARAMS ((tree, tree));
extern void defer_fn PARAMS ((tree));
extern tree get_temp_name PARAMS ((tree, int));
extern tree get_temp_name PARAMS ((tree));
extern void finish_anon_union PARAMS ((tree));
extern tree finish_table PARAMS ((tree, tree, tree, int));
extern void finish_builtin_type PARAMS ((tree, const char *,
@ -4110,6 +4104,9 @@ extern tree handle_class_head PARAMS ((tree, tree, tree));
extern tree lookup_arg_dependent PARAMS ((tree, tree, tree));
extern void finish_static_data_member_decl PARAMS ((tree, tree, tree, int));
extern tree build_artificial_parm PARAMS ((tree, tree));
extern tree get_guard PARAMS ((tree));
extern tree get_guard_cond PARAMS ((tree));
extern tree set_guard PARAMS ((tree));
/* in parse.y */
extern void cp_parse_init PARAMS ((void));

View File

@ -356,7 +356,7 @@ build_up_reference (type, arg, flags)
/* Create a new temporary variable. */
tree targ = arg;
if (toplevel_bindings_p ())
arg = get_temp_name (argtype, 1);
arg = get_temp_name (argtype);
else
{
arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));

View File

@ -8572,19 +8572,19 @@ expand_static_init (decl, init)
else if (! toplevel_bindings_p ())
{
/* Emit code to perform this initialization but once. */
tree temp;
tree if_stmt;
tree then_clause;
tree assignment;
tree temp_init;
tree guard;
tree guard_init;
/* Emit code to perform this initialization but once. This code
looks like:
static int temp = 0;
if (!temp) {
static int guard = 0;
if (!guard) {
// Do initialization.
temp = 1;
guard = 1;
// Register variable for destruction at end of program.
}
@ -8602,14 +8602,13 @@ expand_static_init (decl, init)
In theory, this process should be thread-safe, too; multiple
threads should not be able to initialize the variable more
than once. We don't yet attempt to ensure thread-safety. */
temp = get_temp_name (integer_type_node, 1);
rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
/* Create the guard variable. */
guard = get_guard (decl);
/* Begin the conditional initialization. */
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (cp_build_binary_op (EQ_EXPR, temp,
integer_zero_node),
if_stmt);
finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
then_clause = begin_compound_stmt (/*has_no_scope=*/0);
/* Do the initialization itself. */
@ -8631,16 +8630,16 @@ expand_static_init (decl, init)
the assignment to TEMP into a single expression, ensuring
that when we call finish_expr_stmt the cleanups will not be
run until after TEMP is set to 1. */
temp_init = build_modify_expr (temp, NOP_EXPR, integer_one_node);
guard_init = set_guard (guard);
if (assignment)
{
assignment = tree_cons (NULL_TREE, assignment,
build_tree_list (NULL_TREE,
temp_init));
guard_init));
assignment = build_compound_expr (assignment);
}
else
assignment = temp_init;
assignment = guard_init;
finish_expr_stmt (assignment);
/* Use atexit to register a function for destroying this static

View File

@ -62,7 +62,6 @@ typedef struct priority_info_s {
int destructions_p;
} *priority_info;
static tree get_sentry PARAMS ((tree));
static void mark_vtable_entries PARAMS ((tree));
static void grok_function_init PARAMS ((tree, tree));
static int finish_vtable_vardecl PARAMS ((tree *, void *));
@ -95,6 +94,7 @@ static void write_out_vars PARAMS ((tree));
static void import_export_class PARAMS ((tree));
static tree key_method PARAMS ((tree));
static int compare_options PARAMS ((const PTR, const PTR));
static tree get_guard_bits PARAMS ((tree));
extern int current_class_depth;
@ -2098,32 +2098,24 @@ defer_fn (fn)
/* Hand off a unique name which can be used for variable we don't really
want to know about anyway, for example, the anonymous variables which
are needed to make references work. Declare this thing so we can use it.
The variable created will be of type TYPE.
STATICP is nonzero if this variable should be static. */
The variable created will be of type TYPE, and will have internal
linkage. */
tree
get_temp_name (type, staticp)
get_temp_name (type)
tree type;
int staticp;
{
char buf[sizeof (AUTO_TEMP_FORMAT) + 20];
tree decl;
int toplev = toplevel_bindings_p ();
if (toplev || staticp)
{
sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++);
decl = pushdecl_top_level (build_decl (VAR_DECL, get_identifier (buf), type));
}
else
{
sprintf (buf, AUTO_TEMP_FORMAT, temp_name_counter++);
decl = pushdecl (build_decl (VAR_DECL, get_identifier (buf), type));
}
TREE_USED (decl) = 1;
TREE_STATIC (decl) = staticp;
sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++);
decl = build_decl (VAR_DECL, get_identifier (buf), type);
DECL_ARTIFICIAL (decl) = 1;
TREE_USED (decl) = 1;
TREE_STATIC (decl) = 1;
decl = pushdecl_top_level (decl);
/* If this is a local variable, then lay out its rtl now.
Otherwise, callers of this function are responsible for dealing
@ -2866,37 +2858,111 @@ build_cleanup (decl)
return temp;
}
/* Returns the initialization guard variable for the non-local
variable DECL. */
/* Returns the initialization guard variable for the variable DECL,
which has static storage duration. */
static tree
get_sentry (decl)
tree
get_guard (decl)
tree decl;
{
tree sname;
tree sentry;
tree guard;
/* For a local variable, under the old ABI, we do not try to get a
unique mangled name for the DECL. */
if (!flag_new_abi && !DECL_NAMESPACE_SCOPE_P (decl))
{
guard = get_temp_name (integer_type_node);
rest_of_decl_compilation (guard, NULL_PTR, 0, 0);
}
if (!flag_new_abi)
/* For struct X foo __attribute__((weak)), there is a counter
__snfoo. Since base is already an assembler name, sname should
be globally unique */
sname = get_id_2 ("__sn", DECL_ASSEMBLER_NAME (decl));
else
sname = mangle_guard_variable (decl);
/* For struct X foo __attribute__((weak)), there is a counter
__snfoo. Since base is already an assembler name, sname should
be globally unique */
sentry = IDENTIFIER_GLOBAL_VALUE (sname);
if (! sentry)
guard = IDENTIFIER_GLOBAL_VALUE (sname);
if (! guard)
{
sentry = build_decl (VAR_DECL, sname, integer_type_node);
TREE_PUBLIC (sentry) = 1;
DECL_ARTIFICIAL (sentry) = 1;
TREE_STATIC (sentry) = 1;
TREE_USED (sentry) = 1;
DECL_COMMON (sentry) = 1;
pushdecl_top_level (sentry);
cp_finish_decl (sentry, NULL_TREE, NULL_TREE, 0);
tree guard_type;
/* Under the new ABI, we use a type that is big enough to
contain a mutex as well as an integer counter. */
if (flag_new_abi)
guard_type = long_long_integer_type_node;
else
guard_type = integer_type_node;
guard = build_decl (VAR_DECL, sname, guard_type);
TREE_PUBLIC (guard) = 1;
DECL_ARTIFICIAL (guard) = 1;
TREE_STATIC (guard) = 1;
TREE_USED (guard) = 1;
DECL_COMMON (guard) = 1;
pushdecl_top_level (guard);
cp_finish_decl (guard, NULL_TREE, NULL_TREE, 0);
}
return sentry;
return guard;
}
/* Return those bits of the GUARD variable that should be set when the
guarded entity is actually initialized. */
static tree
get_guard_bits (guard)
tree guard;
{
if (!flag_new_abi)
return guard;
/* Under the new ABI, we only set the first byte of the guard,
in order to leave room for a mutex in the high-order bits. */
guard = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (guard)),
guard);
guard = build1 (NOP_EXPR,
build_pointer_type (char_type_node),
guard);
guard = build1 (INDIRECT_REF, char_type_node, guard);
return guard;
}
/* Return an expression which determines whether or not the GUARD
variable has already been initialized. */
tree
get_guard_cond (guard)
tree guard;
{
tree guard_value;
/* Check to see if the GUARD is zero. */
guard = get_guard_bits (guard);
guard_value = integer_zero_node;
if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
guard_value = convert (TREE_TYPE (guard), guard_value);
return cp_build_binary_op (EQ_EXPR, guard, guard_value);
}
/* Return an expression which sets the GUARD variable, indicating that
the variable being guarded has been initialized. */
tree
set_guard (guard)
tree guard;
{
tree guard_init;
/* Set the GUARD to one. */
guard = get_guard_bits (guard);
guard_init = integer_one_node;
if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard)))
guard_init = convert (TREE_TYPE (guard), guard_init);
return build_modify_expr (guard, NOP_EXPR, guard_init);
}
/* Start the process of running a particular set of global constructors
@ -3201,9 +3267,10 @@ start_static_initialization_or_destruction (decl, initp)
tree decl;
int initp;
{
tree sentry_if_stmt = NULL_TREE;
tree guard_if_stmt = NULL_TREE;
int priority;
tree cond;
tree guard;
tree init_cond;
priority_info pi;
@ -3247,7 +3314,7 @@ start_static_initialization_or_destruction (decl, initp)
/* Conditionalize this initialization on being in the right priority
and being initializing/finalizing appropriately. */
sentry_if_stmt = begin_if_stmt ();
guard_if_stmt = begin_if_stmt ();
cond = cp_build_binary_op (EQ_EXPR,
priority_decl,
build_int_2 (priority, 0));
@ -3257,7 +3324,9 @@ start_static_initialization_or_destruction (decl, initp)
init_cond);
cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, init_cond);
/* We need a sentry if this is an object with external linkage that
/* Assume we don't need a guard. */
guard = NULL_TREE;
/* We need a guard if this is an object with external linkage that
might be initialized in more than one place. (For example, a
static data member of a template, when the data member requires
construction.) */
@ -3265,47 +3334,60 @@ start_static_initialization_or_destruction (decl, initp)
|| DECL_ONE_ONLY (decl)
|| DECL_WEAK (decl)))
{
tree sentry;
tree sentry_cond;
tree guard_cond;
sentry = get_sentry (decl);
guard = get_guard (decl);
/* We do initializations only if the SENTRY is zero, i.e., if we
are the first to initialize the variable. We do destructions
only if the SENTRY is one, i.e., if we are the last to
destroy the variable. */
if (initp)
sentry_cond
/* When using __cxa_atexit, we just check the GUARD as we would
for a local static. */
if (flag_use_cxa_atexit)
{
/* When using __cxa_atexit, we never try to destroy
anything from a static destructor. */
my_friendly_assert (initp, 20000629);
guard_cond = get_guard_cond (guard);
}
/* Under the old ABI, e do initializations only if the GUARD is
zero, i.e., if we are the first to initialize the variable.
We do destructions only if the GUARD is one, i.e., if we are
the last to destroy the variable. */
else if (initp)
guard_cond
= cp_build_binary_op (EQ_EXPR,
build_unary_op (PREINCREMENT_EXPR,
sentry,
guard,
/*noconvert=*/1),
integer_one_node);
else
sentry_cond
guard_cond
= cp_build_binary_op (EQ_EXPR,
build_unary_op (PREDECREMENT_EXPR,
sentry,
guard,
/*noconvert=*/1),
integer_zero_node);
cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, sentry_cond);
cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, guard_cond);
}
finish_if_stmt_cond (cond, sentry_if_stmt);
finish_if_stmt_cond (cond, guard_if_stmt);
return sentry_if_stmt;
/* Under the new ABI, we have not already set the GUARD, so we must
do so now. */
if (guard && initp && flag_new_abi)
finish_expr_stmt (set_guard (guard));
return guard_if_stmt;
}
/* We've just finished generating code to do an initialization or
finalization. SENTRY_IF_STMT is the if-statement we used to guard
finalization. GUARD_IF_STMT is the if-statement we used to guard
the initialization. */
static void
finish_static_initialization_or_destruction (sentry_if_stmt)
tree sentry_if_stmt;
finish_static_initialization_or_destruction (guard_if_stmt)
tree guard_if_stmt;
{
finish_then_clause (sentry_if_stmt);
finish_then_clause (guard_if_stmt);
finish_if_stmt ();
/* Now that we're done with DECL we don't need to pretend to be a
@ -3316,7 +3398,7 @@ finish_static_initialization_or_destruction (sentry_if_stmt)
/* Generate code to do the static initialization of DECL. The
initialization is INIT. If DECL may be initialized more than once
in different object files, SENTRY is the guard variable to
in different object files, GUARD is the guard variable to
check. PRIORITY is the priority for the initialization. */
static void
@ -3325,10 +3407,10 @@ do_static_initialization (decl, init)
tree init;
{
tree expr;
tree sentry_if_stmt;
tree guard_if_stmt;
/* Set up for the initialization. */
sentry_if_stmt
guard_if_stmt
= start_static_initialization_or_destruction (decl,
/*initp=*/1);
@ -3353,11 +3435,11 @@ do_static_initialization (decl, init)
register_dtor_fn (decl);
/* Finsh up. */
finish_static_initialization_or_destruction (sentry_if_stmt);
finish_static_initialization_or_destruction (guard_if_stmt);
}
/* Generate code to do the static destruction of DECL. If DECL may be
initialized more than once in different object files, SENTRY is the
initialized more than once in different object files, GUARD is the
guard variable to check. PRIORITY is the priority for the
destruction. */
@ -3365,7 +3447,7 @@ static void
do_static_destruction (decl)
tree decl;
{
tree sentry_if_stmt;
tree guard_if_stmt;
/* If we're using __cxa_atexit, then destructors are registered
immediately after objects are initialized. */
@ -3376,10 +3458,10 @@ do_static_destruction (decl)
return;
/* Actually do the destruction. */
sentry_if_stmt = start_static_initialization_or_destruction (decl,
guard_if_stmt = start_static_initialization_or_destruction (decl,
/*initp=*/0);
finish_expr_stmt (build_cleanup (decl));
finish_static_initialization_or_destruction (sentry_if_stmt);
finish_static_initialization_or_destruction (guard_if_stmt);
}
/* VARS is a list of variables with static storage duration which may

View File

@ -2729,6 +2729,8 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
return cp_convert (void_type_node, body);
}
/* Create an unnamed variable of the indicated TYPE. */
tree
create_temporary_var (type)
tree type;