mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-22 13:09:50 +08:00
decl2.c (struct priority_info_s): Remove initialization_sequence and destruction_sequence.
* decl2.c (struct priority_info_s): Remove initialization_sequence and destruction_sequence. (start_static_storage_duration_function): Return the body of the function. Convert for function-at-a-time mode. (generate_inits_for_priority): Remove. (finish_static_storage_duration_function): Change prototype. Adjust for function-at-a-time mode. (do_static_initialization): Likewise. (do_static_destruction): Likewise. (do_static_initialization_and_destruction): Remove. (start_static_initialization_or_destruction): New function. (finish_static_initialization_or_destruction): Likewise. (get_priority_info): Don't manipulation initialization_sequence or destruction_sequence. (prune_vars_needing_no_initialization): New function. (write_out_vars): Likewise. (finish_file): Use the various new functions instead of the old. From-SVN: r29731
This commit is contained in:
parent
d9d5c9de1c
commit
313bc2c262
@ -1,3 +1,23 @@
|
||||
1999-09-30 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* decl2.c (struct priority_info_s): Remove initialization_sequence
|
||||
and destruction_sequence.
|
||||
(start_static_storage_duration_function): Return the body of the
|
||||
function. Convert for function-at-a-time mode.
|
||||
(generate_inits_for_priority): Remove.
|
||||
(finish_static_storage_duration_function): Change prototype.
|
||||
Adjust for function-at-a-time mode.
|
||||
(do_static_initialization): Likewise.
|
||||
(do_static_destruction): Likewise.
|
||||
(do_static_initialization_and_destruction): Remove.
|
||||
(start_static_initialization_or_destruction): New function.
|
||||
(finish_static_initialization_or_destruction): Likewise.
|
||||
(get_priority_info): Don't manipulation initialization_sequence or
|
||||
destruction_sequence.
|
||||
(prune_vars_needing_no_initialization): New function.
|
||||
(write_out_vars): Likewise.
|
||||
(finish_file): Use the various new functions instead of the old.
|
||||
|
||||
Thu Sep 30 00:13:27 1999 Dirk Zoller <duz@rtsffm.com>
|
||||
|
||||
* cp-tree.h (warn_float_equal): Declare.
|
||||
|
553
gcc/cp/decl2.c
553
gcc/cp/decl2.c
@ -53,12 +53,6 @@ extern cpp_reader parse_in;
|
||||
/* This structure contains information about the initializations
|
||||
and/or destructions required for a particular priority level. */
|
||||
typedef struct priority_info_s {
|
||||
/* A label indicating where we should generate the next
|
||||
initialization with this priority. */
|
||||
rtx initialization_sequence;
|
||||
/* A label indicating where we should generate the next destruction
|
||||
with this priority. */
|
||||
rtx destruction_sequence;
|
||||
/* Non-zero if there have been any initializations at this priority
|
||||
throughout the translation unit. */
|
||||
int initializations_p;
|
||||
@ -85,16 +79,19 @@ static tree decl_namespace PROTO((tree));
|
||||
static tree validate_nonmember_using_decl PROTO((tree, tree *, tree *));
|
||||
static void do_nonmember_using_decl PROTO((tree, tree, tree, tree,
|
||||
tree *, tree *));
|
||||
static void start_static_storage_duration_function PROTO((void));
|
||||
static int generate_inits_for_priority PROTO((splay_tree_node, void *));
|
||||
static void finish_static_storage_duration_function PROTO((void));
|
||||
static tree start_static_storage_duration_function PROTO((void));
|
||||
static void finish_static_storage_duration_function PROTO((tree));
|
||||
static priority_info get_priority_info PROTO((int));
|
||||
static void do_static_initialization PROTO((tree, tree, tree, int));
|
||||
static void do_static_destruction PROTO((tree, tree, int));
|
||||
static void do_static_initialization_and_destruction PROTO((tree, tree));
|
||||
static void do_static_initialization PROTO((tree, tree));
|
||||
static void do_static_destruction PROTO((tree));
|
||||
static tree start_static_initialization_or_destruction PROTO((tree, int));
|
||||
static void finish_static_initialization_or_destruction PROTO((tree));
|
||||
static void generate_ctor_or_dtor_function PROTO((int, int));
|
||||
static int generate_ctor_and_dtor_functions_for_priority
|
||||
PROTO((splay_tree_node, void *));
|
||||
static tree prune_vars_needing_no_initialization PROTO((tree));
|
||||
static void write_out_vars PROTO((tree));
|
||||
|
||||
extern int current_class_depth;
|
||||
|
||||
/* A list of virtual function tables we must make sure to write out. */
|
||||
@ -2916,13 +2913,14 @@ static splay_tree priority_info_map;
|
||||
It is assumed that this function will only be called once per
|
||||
translation unit. */
|
||||
|
||||
static void
|
||||
static tree
|
||||
start_static_storage_duration_function ()
|
||||
{
|
||||
static unsigned ssdf_number;
|
||||
|
||||
tree parm_types;
|
||||
tree type;
|
||||
tree body;
|
||||
char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
|
||||
|
||||
/* Create the identifier for this function. It will be of the form
|
||||
@ -3000,86 +2998,17 @@ start_static_storage_duration_function ()
|
||||
start_function (/*specs=*/NULL_TREE,
|
||||
ssdf_decl,
|
||||
/*attrs=*/NULL_TREE,
|
||||
SF_PRE_PARSED | SF_EXPAND);
|
||||
SF_PRE_PARSED);
|
||||
|
||||
/* Set up the scope of the outermost block in the function. */
|
||||
store_parm_decls ();
|
||||
pushlevel (0);
|
||||
clear_last_expr ();
|
||||
push_momentary ();
|
||||
expand_start_bindings (0);
|
||||
body = begin_compound_stmt (/*has_no_scope=*/0);
|
||||
|
||||
/* This function must not be deferred because we are depending on
|
||||
its compilation to tell us what is TREE_SYMBOL_REFERENCED. */
|
||||
current_function_cannot_inline
|
||||
= "static storage duration functions cannot be inlined";
|
||||
}
|
||||
|
||||
/* Generate the initialization code for the priority indicated in N. */
|
||||
|
||||
static int
|
||||
generate_inits_for_priority (n, data)
|
||||
splay_tree_node n;
|
||||
void *data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
int priority = (int) n->key;
|
||||
priority_info pi = (priority_info) n->value;
|
||||
|
||||
/* For each priority N which has been used generate code which looks
|
||||
like:
|
||||
|
||||
if (__priority == N) {
|
||||
if (__initialize_p)
|
||||
...
|
||||
else
|
||||
...
|
||||
}
|
||||
|
||||
We use the sequences we've accumulated to fill in the `...'s. */
|
||||
expand_start_cond (build_binary_op (EQ_EXPR,
|
||||
priority_decl,
|
||||
build_int_2 (priority, 0)),
|
||||
/*exit_flag=*/0);
|
||||
|
||||
/* Do the initializations. */
|
||||
expand_start_cond (build_binary_op (NE_EXPR,
|
||||
initialize_p_decl,
|
||||
integer_zero_node),
|
||||
/*exit_flag=*/0);
|
||||
if (pi->initialization_sequence)
|
||||
{
|
||||
rtx insns;
|
||||
|
||||
push_to_sequence (pi->initialization_sequence);
|
||||
insns = gen_sequence ();
|
||||
end_sequence ();
|
||||
|
||||
emit_insn (insns);
|
||||
pi->initialization_sequence = NULL_RTX;
|
||||
pi->initializations_p = 1;
|
||||
}
|
||||
|
||||
/* Do the destructions. */
|
||||
expand_start_else ();
|
||||
if (pi->destruction_sequence)
|
||||
{
|
||||
rtx insns;
|
||||
|
||||
push_to_sequence (pi->destruction_sequence);
|
||||
insns = gen_sequence ();
|
||||
end_sequence ();
|
||||
|
||||
emit_insn (insns);
|
||||
pi->destruction_sequence = NULL_RTX;
|
||||
pi->destructions_p = 1;
|
||||
}
|
||||
|
||||
/* Close out the conditionals. */
|
||||
expand_end_cond ();
|
||||
expand_end_cond ();
|
||||
|
||||
/* Don't stop iterating. */
|
||||
return 0;
|
||||
return body;
|
||||
}
|
||||
|
||||
/* Finish the generation of the function which performs initialization
|
||||
@ -3087,17 +3016,12 @@ generate_inits_for_priority (n, data)
|
||||
this point, no more such objects can be created. */
|
||||
|
||||
static void
|
||||
finish_static_storage_duration_function ()
|
||||
finish_static_storage_duration_function (body)
|
||||
tree body;
|
||||
{
|
||||
splay_tree_foreach (priority_info_map,
|
||||
generate_inits_for_priority,
|
||||
/*data=*/0);
|
||||
|
||||
/* Close out the function. */
|
||||
expand_end_bindings (getdecls (), 1, 0);
|
||||
poplevel (1, 0, 0);
|
||||
pop_momentary ();
|
||||
finish_function (lineno, 0);
|
||||
finish_compound_stmt (/*has_no_scope=*/0, body);
|
||||
expand_body (finish_function (lineno, 0));
|
||||
}
|
||||
|
||||
/* Return the information about the indicated PRIORITY level. If no
|
||||
@ -3118,8 +3042,6 @@ get_priority_info (priority)
|
||||
/* Create a new priority information structure, and insert it
|
||||
into the map. */
|
||||
pi = (priority_info) xmalloc (sizeof (struct priority_info_s));
|
||||
pi->initialization_sequence = NULL_RTX;
|
||||
pi->destruction_sequence = NULL_RTX;
|
||||
pi->initializations_p = 0;
|
||||
pi->destructions_p = 0;
|
||||
splay_tree_insert (priority_info_map,
|
||||
@ -3132,175 +3054,33 @@ get_priority_info (priority)
|
||||
return pi;
|
||||
}
|
||||
|
||||
/* 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
|
||||
check. PRIORITY is the priority for the initialization. */
|
||||
/* Set up to handle the initialization or destruction of DECL. If
|
||||
INITP is non-zero, we are initializing the variable. Otherwise, we
|
||||
are destroying it. */
|
||||
|
||||
static void
|
||||
do_static_initialization (decl, init, sentry, priority)
|
||||
static tree
|
||||
start_static_initialization_or_destruction (decl, initp)
|
||||
tree decl;
|
||||
tree init;
|
||||
tree sentry;
|
||||
int priority;
|
||||
int initp;
|
||||
{
|
||||
priority_info pi;
|
||||
|
||||
/* Get the priority information for this PRIORITY, */
|
||||
pi = get_priority_info (priority);
|
||||
if (!pi->initialization_sequence)
|
||||
start_sequence ();
|
||||
else
|
||||
push_to_sequence (pi->initialization_sequence);
|
||||
|
||||
/* Tell the debugger that we are at the location of the static
|
||||
variable in question. */
|
||||
emit_note (input_filename, lineno);
|
||||
|
||||
/* If there's a SENTRY, we only do the initialization if it is
|
||||
zero, i.e., if we are the first to initialize it. */
|
||||
if (sentry)
|
||||
expand_start_cond (build_binary_op (EQ_EXPR,
|
||||
build_unary_op (PREINCREMENT_EXPR,
|
||||
sentry,
|
||||
/*noconvert=*/0),
|
||||
integer_one_node),
|
||||
/*exit_flag=*/0);
|
||||
|
||||
/* Prepare a binding level for temporaries created during the
|
||||
initialization. */
|
||||
expand_start_target_temps ();
|
||||
|
||||
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|
||||
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
|
||||
expand_expr (build_aggr_init (decl, init, 0),
|
||||
const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
else if (TREE_CODE (init) == TREE_VEC)
|
||||
expand_expr (build_vec_init (decl, TREE_VEC_ELT (init, 0),
|
||||
TREE_VEC_ELT (init, 1),
|
||||
TREE_VEC_ELT (init, 2), 0),
|
||||
const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
else
|
||||
expand_assignment (decl, init, 0, 0);
|
||||
|
||||
/* The expression might have involved increments and decrements. */
|
||||
emit_queue ();
|
||||
|
||||
/* Cleanup any temporaries needed for the initial value. */
|
||||
expand_end_target_temps ();
|
||||
|
||||
/* Cleanup any deferred pops from function calls. This would be done
|
||||
by expand_end_cond, but we also need it when !SENTRY, since we are
|
||||
constructing these sequences by parts. */
|
||||
do_pending_stack_adjust ();
|
||||
|
||||
/* Close the conditional opened above. */
|
||||
if (sentry)
|
||||
expand_end_cond ();
|
||||
|
||||
/* Save the sequence for later use. */
|
||||
pi->initialization_sequence = get_insns ();
|
||||
end_sequence ();
|
||||
}
|
||||
|
||||
/* Generate code to do the static destruction of DECL. If DECL may be
|
||||
initialized more than once in different object files, SENTRY is the
|
||||
guard variable to check. PRIORITY is the priority for the
|
||||
destruction. */
|
||||
|
||||
static void
|
||||
do_static_destruction (decl, sentry, priority)
|
||||
tree decl;
|
||||
tree sentry;
|
||||
int priority;
|
||||
{
|
||||
rtx new_insns;
|
||||
priority_info pi;
|
||||
|
||||
/* If we don't need a destructor, there's nothing to do. */
|
||||
if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
|
||||
return;
|
||||
|
||||
/* Get the priority information for this PRIORITY, */
|
||||
pi = get_priority_info (priority);
|
||||
if (!pi->destruction_sequence)
|
||||
start_sequence ();
|
||||
else
|
||||
push_to_sequence (pi->destruction_sequence);
|
||||
|
||||
/* Start a new sequence to handle just this destruction. */
|
||||
start_sequence ();
|
||||
|
||||
/* Tell the debugger that we are at the location of the static
|
||||
variable in question. */
|
||||
emit_note (input_filename, lineno);
|
||||
|
||||
/* If there's a SENTRY, we only do the destruction if it is one,
|
||||
i.e., if we are the last to destroy it. */
|
||||
if (sentry)
|
||||
expand_start_cond (build_binary_op (EQ_EXPR,
|
||||
build_unary_op (PREDECREMENT_EXPR,
|
||||
sentry,
|
||||
/*nonconvert=*/1),
|
||||
integer_zero_node),
|
||||
/*exit_flag=*/0);
|
||||
|
||||
/* Actually do the destruction. */
|
||||
expand_expr_stmt (build_cleanup (decl));
|
||||
|
||||
/* Cleanup any deferred pops from function calls. This would be done
|
||||
by expand_end_cond, but we also need it when !SENTRY, since we are
|
||||
constructing these sequences by parts. */
|
||||
do_pending_stack_adjust ();
|
||||
|
||||
/* Close the conditional opened above. */
|
||||
if (sentry)
|
||||
expand_end_cond ();
|
||||
|
||||
/* Insert the NEW_INSNS before the current insns. (Destructions are
|
||||
run in reverse order of initializations.) */
|
||||
new_insns = gen_sequence ();
|
||||
end_sequence ();
|
||||
if (pi->destruction_sequence)
|
||||
emit_insn_before (new_insns, pi->destruction_sequence);
|
||||
else
|
||||
emit_insn (new_insns);
|
||||
|
||||
/* Save the sequence for later use. */
|
||||
pi->destruction_sequence = get_insns ();
|
||||
end_sequence ();
|
||||
}
|
||||
|
||||
/* Add code to the static storage duration function that will handle
|
||||
DECL (a static variable that needs initializing and/or destruction)
|
||||
with the indicated PRIORITY. If DECL needs initializing, INIT is
|
||||
the initializer. */
|
||||
|
||||
static void
|
||||
do_static_initialization_and_destruction (decl, init)
|
||||
tree decl;
|
||||
tree init;
|
||||
{
|
||||
tree sentry = NULL_TREE;
|
||||
tree sentry_if_stmt = NULL_TREE;
|
||||
int priority;
|
||||
tree cond;
|
||||
tree init_cond;
|
||||
priority_info pi;
|
||||
|
||||
/* Deal gracefully with error. */
|
||||
if (decl == error_mark_node)
|
||||
return;
|
||||
/* Figure out the priority for this declaration. */
|
||||
priority = DECL_INIT_PRIORITY (decl);
|
||||
if (!priority)
|
||||
priority = DEFAULT_INIT_PRIORITY;
|
||||
|
||||
/* The only things that can be initialized are variables. */
|
||||
my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420);
|
||||
|
||||
/* If this object is not defined, we don't need to do anything
|
||||
here. */
|
||||
if (DECL_EXTERNAL (decl))
|
||||
return;
|
||||
|
||||
/* Also, if the initializer already contains errors, we can bail out
|
||||
now. */
|
||||
if (init && TREE_CODE (init) == TREE_LIST
|
||||
&& value_member (error_mark_node, init))
|
||||
return;
|
||||
/* Remember that we had an initialization or finalization at this
|
||||
priority. */
|
||||
pi = get_priority_info (priority);
|
||||
if (initp)
|
||||
pi->initializations_p = 1;
|
||||
else
|
||||
pi->destructions_p = 1;
|
||||
|
||||
/* Trick the compiler into thinking we are at the file and line
|
||||
where DECL was declared so that error-messages make sense, and so
|
||||
@ -3327,20 +3107,64 @@ do_static_initialization_and_destruction (decl, init)
|
||||
DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
|
||||
}
|
||||
|
||||
/* Conditionalize this initialization on being in the right priority
|
||||
and being initializing/finalizing appropriately. */
|
||||
sentry_if_stmt = begin_if_stmt ();
|
||||
cond = build_binary_op (EQ_EXPR,
|
||||
priority_decl,
|
||||
build_int_2 (priority, 0));
|
||||
init_cond = initp ? integer_one_node : integer_zero_node;
|
||||
init_cond = build_binary_op (EQ_EXPR,
|
||||
initialize_p_decl,
|
||||
init_cond);
|
||||
cond = build_binary_op (TRUTH_ANDIF_EXPR, cond, init_cond);
|
||||
|
||||
/* We need a sentry if this is an object with external linkage that
|
||||
might be initialized in more than one place. */
|
||||
if (TREE_PUBLIC (decl) && (DECL_COMMON (decl)
|
||||
|| DECL_ONE_ONLY (decl)
|
||||
|| DECL_WEAK (decl)))
|
||||
sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
|
||||
{
|
||||
tree sentry;
|
||||
tree sentry_cond;
|
||||
|
||||
/* Generate the code to actually do the intialization and
|
||||
destruction. */
|
||||
priority = DECL_INIT_PRIORITY (decl);
|
||||
if (!priority)
|
||||
priority = DEFAULT_INIT_PRIORITY;
|
||||
do_static_initialization (decl, init, sentry, priority);
|
||||
do_static_destruction (decl, sentry, priority);
|
||||
sentry = get_sentry (DECL_ASSEMBLER_NAME (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 = build_binary_op (EQ_EXPR,
|
||||
build_unary_op (PREINCREMENT_EXPR,
|
||||
sentry,
|
||||
/*noconvert=*/1),
|
||||
integer_one_node);
|
||||
else
|
||||
sentry_cond = build_binary_op (EQ_EXPR,
|
||||
build_unary_op (PREDECREMENT_EXPR,
|
||||
sentry,
|
||||
/*noconvert=*/1),
|
||||
integer_zero_node);
|
||||
|
||||
cond = build_binary_op (TRUTH_ANDIF_EXPR, cond, sentry_cond);
|
||||
}
|
||||
|
||||
finish_if_stmt_cond (cond, sentry_if_stmt);
|
||||
|
||||
return sentry_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
|
||||
the initialization. */
|
||||
|
||||
static void
|
||||
finish_static_initialization_or_destruction (sentry_if_stmt)
|
||||
tree sentry_if_stmt;
|
||||
{
|
||||
finish_then_clause (sentry_if_stmt);
|
||||
finish_if_stmt ();
|
||||
|
||||
/* Now that we're done with DECL we don't need to pretend to be a
|
||||
member of its class any longer. */
|
||||
@ -3348,6 +3172,127 @@ do_static_initialization_and_destruction (decl, init)
|
||||
DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
|
||||
}
|
||||
|
||||
/* 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
|
||||
check. PRIORITY is the priority for the initialization. */
|
||||
|
||||
static void
|
||||
do_static_initialization (decl, init)
|
||||
tree decl;
|
||||
tree init;
|
||||
{
|
||||
tree expr;
|
||||
tree sentry_if_stmt;
|
||||
|
||||
/* Set up for the initialization. */
|
||||
sentry_if_stmt
|
||||
= start_static_initialization_or_destruction (decl,
|
||||
/*initp=*/1);
|
||||
|
||||
/* Do the initialization itself. */
|
||||
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|
||||
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
|
||||
expr = build_aggr_init (decl, init, 0);
|
||||
else if (TREE_CODE (init) == TREE_VEC)
|
||||
expr = build_vec_init (decl, TREE_VEC_ELT (init, 0),
|
||||
TREE_VEC_ELT (init, 1),
|
||||
TREE_VEC_ELT (init, 2), 0);
|
||||
else
|
||||
{
|
||||
expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
|
||||
TREE_SIDE_EFFECTS (expr) = 1;
|
||||
}
|
||||
finish_expr_stmt (expr);
|
||||
|
||||
/* Finsh up. */
|
||||
finish_static_initialization_or_destruction (sentry_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
|
||||
guard variable to check. PRIORITY is the priority for the
|
||||
destruction. */
|
||||
|
||||
static void
|
||||
do_static_destruction (decl)
|
||||
tree decl;
|
||||
{
|
||||
tree sentry_if_stmt;
|
||||
|
||||
/* If we don't need a destructor, there's nothing to do. */
|
||||
if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
|
||||
return;
|
||||
|
||||
/* Actually do the destruction. */
|
||||
sentry_if_stmt = start_static_initialization_or_destruction (decl,
|
||||
/*initp=*/0);
|
||||
finish_expr_stmt (build_cleanup (decl));
|
||||
finish_static_initialization_or_destruction (sentry_if_stmt);
|
||||
}
|
||||
|
||||
/* VARS is a list of variables with static storage duration which may
|
||||
need initialization and/or finalization. Remove those variables
|
||||
that don't really need to be initialized or finalized, and return
|
||||
the resulting list. The order in which the variables appear in
|
||||
VARS is in reverse order of the order in which they should actually
|
||||
be initialized. The list we return is in the unreversed order;
|
||||
i.e., the first variable should be initialized first. */
|
||||
|
||||
static tree
|
||||
prune_vars_needing_no_initialization (vars)
|
||||
tree vars;
|
||||
{
|
||||
tree var;
|
||||
tree result;
|
||||
|
||||
for (var = vars, result = NULL_TREE;
|
||||
var;
|
||||
var = TREE_CHAIN (var))
|
||||
{
|
||||
tree decl = TREE_VALUE (var);
|
||||
tree init = TREE_PURPOSE (var);
|
||||
|
||||
/* Deal gracefully with error. */
|
||||
if (decl == error_mark_node)
|
||||
continue;
|
||||
|
||||
/* The only things that can be initialized are variables. */
|
||||
my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420);
|
||||
|
||||
/* If this object is not defined, we don't need to do anything
|
||||
here. */
|
||||
if (DECL_EXTERNAL (decl))
|
||||
continue;
|
||||
|
||||
/* Also, if the initializer already contains errors, we can bail
|
||||
out now. */
|
||||
if (init && TREE_CODE (init) == TREE_LIST
|
||||
&& value_member (error_mark_node, init))
|
||||
continue;
|
||||
|
||||
/* This variable is going to need initialization and/or
|
||||
finalization, so we add it to the list. */
|
||||
result = tree_cons (init, decl, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Make sure we have told the back end about all the variables in
|
||||
VARS. */
|
||||
|
||||
static void
|
||||
write_out_vars (vars)
|
||||
tree vars;
|
||||
{
|
||||
tree v;
|
||||
|
||||
for (v = vars; v; v = TREE_CHAIN (v))
|
||||
if (! TREE_ASM_WRITTEN (TREE_VALUE (v)))
|
||||
rest_of_decl_compilation (TREE_VALUE (v), 0, 1, 1);
|
||||
}
|
||||
|
||||
/* Generate a static constructor (if CONSTRUCTOR_P) or destructor
|
||||
(otherwise) that will initialize all gobal objects with static
|
||||
storage duration having the indicated PRIORITY. */
|
||||
@ -3480,10 +3425,6 @@ finish_file ()
|
||||
|
||||
do
|
||||
{
|
||||
/* Non-zero if we need a static storage duration function on
|
||||
this iteration through the loop. */
|
||||
int need_ssdf_p = 0;
|
||||
|
||||
reconsider = 0;
|
||||
|
||||
/* If there are templates that we've put off instantiating, do
|
||||
@ -3499,41 +3440,51 @@ finish_file ()
|
||||
reconsider = 1;
|
||||
|
||||
/* The list of objects with static storage duration is built up
|
||||
in reverse order, so we reverse it here. We also clear
|
||||
STATIC_AGGREGATES so that any new aggregates added during the
|
||||
initialization of these will be initialized in the correct
|
||||
order when we next come around the loop. */
|
||||
vars = nreverse (static_aggregates);
|
||||
in reverse order. We clear STATIC_AGGREGATES so that any new
|
||||
aggregates added during the initialization of these will be
|
||||
initialized in the correct order when we next come around the
|
||||
loop. */
|
||||
vars = prune_vars_needing_no_initialization (static_aggregates);
|
||||
static_aggregates = NULL_TREE;
|
||||
while (vars)
|
||||
{
|
||||
if (! TREE_ASM_WRITTEN (TREE_VALUE (vars)))
|
||||
rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1);
|
||||
if (!need_ssdf_p)
|
||||
{
|
||||
/* We need to start a new initialization function each
|
||||
time through the loop. That's because we need to
|
||||
know which vtables have been referenced, and
|
||||
TREE_SYMBOL_REFERENCED isn't computed until a
|
||||
function is finished, and written out. That's a
|
||||
deficiency in the back-end. When this is fixed,
|
||||
these initialization functions could all become
|
||||
inline, with resulting performance improvements. */
|
||||
start_static_storage_duration_function ();
|
||||
need_ssdf_p = 1;
|
||||
}
|
||||
|
||||
do_static_initialization_and_destruction (TREE_VALUE (vars),
|
||||
TREE_PURPOSE (vars));
|
||||
if (vars)
|
||||
{
|
||||
tree v;
|
||||
|
||||
/* We need to start a new initialization function each time
|
||||
through the loop. That's because we need to know which
|
||||
vtables have been referenced, and TREE_SYMBOL_REFERENCED
|
||||
isn't computed until a function is finished, and written
|
||||
out. That's a deficiency in the back-end. When this is
|
||||
fixed, these initialization functions could all become
|
||||
inline, with resulting performance improvements. */
|
||||
tree ssdf_body = start_static_storage_duration_function ();
|
||||
|
||||
/* Make sure the back end knows about all the variables. */
|
||||
write_out_vars (vars);
|
||||
|
||||
/* First generate code to do all the initializations. */
|
||||
for (v = vars; v; v = TREE_CHAIN (v))
|
||||
do_static_initialization (TREE_VALUE (v),
|
||||
TREE_PURPOSE (v));
|
||||
|
||||
/* Then, generate code to do all the destructions. Do these
|
||||
in reverse order so that the most recently constructed
|
||||
variable is the first destroyed. */
|
||||
vars = nreverse (vars);
|
||||
for (v = vars; v; v = TREE_CHAIN (v))
|
||||
do_static_destruction (TREE_VALUE (v));
|
||||
|
||||
/* Finish up the static storage duration function for this
|
||||
round. */
|
||||
finish_static_storage_duration_function (ssdf_body);
|
||||
|
||||
/* All those initializations and finalizations might cause
|
||||
us to need more inline functions, more template
|
||||
instantiations, etc. */
|
||||
reconsider = 1;
|
||||
vars = TREE_CHAIN (vars);
|
||||
}
|
||||
|
||||
/* Finish up the static storage duration function for this
|
||||
round. */
|
||||
if (need_ssdf_p)
|
||||
finish_static_storage_duration_function ();
|
||||
|
||||
/* Go through the various inline functions, and see if any need
|
||||
synthesizing. */
|
||||
for (i = 0; i < saved_inlines_used; ++i)
|
||||
|
Loading…
Reference in New Issue
Block a user