Commit 873c7164 by Mark Mitchell Committed by Mark Mitchell

re PR target/33579 (INIT_PRIORITY is broken)

	PR target/33579
	* tree.h (DECL_INIT_PRIORITY): Do not require
	DECL_HAS_INIT_PRIORITY_P.
	(DECL_FINI_PRIORITY): Likewise.
	* tree.c (decl_init_priority_lookup): Remove assert.
	(decl_fini_priority_insert): Likewise.
	* cgraphunit.c (static_ctors): Make it a VEC.
	(static_dtors): Likewise.
	(record_cdtor_fn): Adjust accordingly.
	(build_cdtor): Generate multiple functions for each initialization
	priority.
	(compare_ctor): New function.
	(compare_dtor): Likewise.
	(cgraph_build_cdtor_fns): Sort the functions by priority before
	calling build_cdtor.
	(cgraph_build_static_cdtor): Put the priority in the function's
	name.

From-SVN: r129918
parent 7ef52af4
2007-11-05 Mark Mitchell <mark@codesourcery.com>
PR target/33579
* tree.h (DECL_INIT_PRIORITY): Do not require
DECL_HAS_INIT_PRIORITY_P.
(DECL_FINI_PRIORITY): Likewise.
* tree.c (decl_init_priority_lookup): Remove assert.
(decl_fini_priority_insert): Likewise.
* cgraphunit.c (static_ctors): Make it a VEC.
(static_dtors): Likewise.
(record_cdtor_fn): Adjust accordingly.
(build_cdtor): Generate multiple functions for each initialization
priority.
(compare_ctor): New function.
(compare_dtor): Likewise.
(cgraph_build_cdtor_fns): Sort the functions by priority before
calling build_cdtor.
(cgraph_build_static_cdtor): Put the priority in the function's
name.
2007-11-05 H.J. Lu <hongjiu.lu@intel.com> 2007-11-05 H.J. Lu <hongjiu.lu@intel.com>
PR driver/32632 PR driver/32632
...@@ -158,8 +158,10 @@ static void cgraph_output_pending_asms (void); ...@@ -158,8 +158,10 @@ static void cgraph_output_pending_asms (void);
static FILE *cgraph_dump_file; static FILE *cgraph_dump_file;
static GTY (()) tree static_ctors; /* A vector of FUNCTION_DECLs declared as static constructors. */
static GTY (()) tree static_dtors; static GTY (()) VEC(tree, gc) *static_ctors;
/* A vector of FUNCTION_DECLs declared as static destructors. */
static GTY (()) VEC(tree, gc) *static_dtors;
/* When target does not have ctors and dtors, we call all constructor /* When target does not have ctors and dtors, we call all constructor
and destructor by special initialization/destruction function and destructor by special initialization/destruction function
...@@ -179,12 +181,12 @@ record_cdtor_fn (tree fndecl) ...@@ -179,12 +181,12 @@ record_cdtor_fn (tree fndecl)
if (DECL_STATIC_CONSTRUCTOR (fndecl)) if (DECL_STATIC_CONSTRUCTOR (fndecl))
{ {
static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors); VEC_safe_push (tree, gc, static_ctors, fndecl);
DECL_STATIC_CONSTRUCTOR (fndecl) = 0; DECL_STATIC_CONSTRUCTOR (fndecl) = 0;
} }
if (DECL_STATIC_DESTRUCTOR (fndecl)) if (DECL_STATIC_DESTRUCTOR (fndecl))
{ {
static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors); VEC_safe_push (tree, gc, static_dtors, fndecl);
DECL_STATIC_DESTRUCTOR (fndecl) = 0; DECL_STATIC_DESTRUCTOR (fndecl) = 0;
} }
DECL_INLINE (fndecl) = 1; DECL_INLINE (fndecl) = 1;
...@@ -193,22 +195,98 @@ record_cdtor_fn (tree fndecl) ...@@ -193,22 +195,98 @@ record_cdtor_fn (tree fndecl)
cgraph_mark_reachable_node (node); cgraph_mark_reachable_node (node);
} }
/* Synthesize a function which calls all the global ctors or global /* Define global constructors/destructor functions for the CDTORS, of
dtors in this file. This is only used for targets which do not which they are LEN. The CDTORS are sorted by initialization
support .ctors/.dtors sections. */ priority. If CTOR_P is true, these are constructors; otherwise,
they are destructors. */
static void static void
build_cdtor (int method_type, tree cdtors) build_cdtor (bool ctor_p, tree *cdtors, size_t len)
{ {
tree body = 0; size_t i;
if (!cdtors) i = 0;
return; while (i < len)
{
tree body;
tree fn;
priority_type priority;
priority = 0;
body = NULL_TREE;
/* Find the next batch of constructors/destructors with the same
initialization priority. */
do
{
priority_type p;
fn = cdtors[i];
p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
if (!body)
priority = p;
else if (p != priority)
break;
append_to_statement_list (build_function_call_expr (fn, 0),
&body);
++i;
}
while (i < len);
gcc_assert (body != NULL_TREE);
/* Generate a function to call all the function of like
priority. */
cgraph_build_static_cdtor (ctor_p ? 'I' : 'D', body, priority);
}
}
/* Comparison function for qsort. P1 and P2 are actually of type
"tree *" and point to static constructors. DECL_INIT_PRIORITY is
used to determine the sort order. */
for (; cdtors; cdtors = TREE_CHAIN (cdtors)) static int
append_to_statement_list (build_function_call_expr (TREE_VALUE (cdtors), 0), compare_ctor (const void *p1, const void *p2)
&body); {
tree f1;
tree f2;
int priority1;
int priority2;
f1 = *(const tree *)p1;
f2 = *(const tree *)p2;
priority1 = DECL_INIT_PRIORITY (f1);
priority2 = DECL_INIT_PRIORITY (f2);
if (priority1 < priority2)
return -1;
else if (priority1 > priority2)
return 1;
else
/* Ensure a stable sort. */
return (const tree *)p1 - (const tree *)p2;
}
/* Comparison function for qsort. P1 and P2 are actually of type
"tree *" and point to static destructors. DECL_FINI_PRIORITY is
used to determine the sort order. */
cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY); static int
compare_dtor (const void *p1, const void *p2)
{
tree f1;
tree f2;
int priority1;
int priority2;
f1 = *(const tree *)p1;
f2 = *(const tree *)p2;
priority1 = DECL_FINI_PRIORITY (f1);
priority2 = DECL_FINI_PRIORITY (f2);
if (priority1 < priority2)
return -1;
else if (priority1 > priority2)
return 1;
else
/* Ensure a stable sort. */
return (const tree *)p1 - (const tree *)p2;
} }
/* Generate functions to call static constructors and destructors /* Generate functions to call static constructors and destructors
...@@ -218,17 +296,30 @@ build_cdtor (int method_type, tree cdtors) ...@@ -218,17 +296,30 @@ build_cdtor (int method_type, tree cdtors)
static void static void
cgraph_build_cdtor_fns (void) cgraph_build_cdtor_fns (void)
{ {
if (!targetm.have_ctors_dtors) if (!VEC_empty (tree, static_ctors))
{ {
build_cdtor ('I', static_ctors); gcc_assert (!targetm.have_ctors_dtors);
static_ctors = NULL_TREE; qsort (VEC_address (tree, static_ctors),
build_cdtor ('D', static_dtors); VEC_length (tree, static_ctors),
static_dtors = NULL_TREE; sizeof (tree),
compare_ctor);
build_cdtor (/*ctor_p=*/true,
VEC_address (tree, static_ctors),
VEC_length (tree, static_ctors));
VEC_truncate (tree, static_ctors, 0);
} }
else
if (!VEC_empty (tree, static_dtors))
{ {
gcc_assert (!static_ctors); gcc_assert (!targetm.have_ctors_dtors);
gcc_assert (!static_dtors); qsort (VEC_address (tree, static_dtors),
VEC_length (tree, static_dtors),
sizeof (tree),
compare_dtor);
build_cdtor (/*ctor_p=*/false,
VEC_address (tree, static_dtors),
VEC_length (tree, static_dtors));
VEC_truncate (tree, static_dtors, 0);
} }
} }
...@@ -1364,9 +1455,10 @@ cgraph_optimize (void) ...@@ -1364,9 +1455,10 @@ cgraph_optimize (void)
} }
#endif #endif
} }
/* Generate and emit a static constructor or destructor. WHICH must be /* Generate and emit a static constructor or destructor. WHICH must
one of 'I' or 'D'. BODY should be a STATEMENT_LIST containing be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
GENERIC statements. */ is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
initialization priority fot this constructor or destructor. */
void void
cgraph_build_static_cdtor (char which, tree body, int priority) cgraph_build_static_cdtor (char which, tree body, int priority)
...@@ -1375,7 +1467,10 @@ cgraph_build_static_cdtor (char which, tree body, int priority) ...@@ -1375,7 +1467,10 @@ cgraph_build_static_cdtor (char which, tree body, int priority)
char which_buf[16]; char which_buf[16];
tree decl, name, resdecl; tree decl, name, resdecl;
sprintf (which_buf, "%c_%d", which, counter++); /* The priority is encoded in the constructor or destructor name.
collect2 will sort the names and arrange that they are called at
program startup. */
sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
name = get_file_function_name (which_buf); name = get_file_function_name (which_buf);
decl = build_decl (FUNCTION_DECL, name, decl = build_decl (FUNCTION_DECL, name,
......
...@@ -4306,9 +4306,6 @@ decl_init_priority_lookup (tree decl) ...@@ -4306,9 +4306,6 @@ decl_init_priority_lookup (tree decl)
struct tree_map_base in; struct tree_map_base in;
gcc_assert (VAR_OR_FUNCTION_DECL_P (decl)); gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
gcc_assert (TREE_CODE (decl) == VAR_DECL
? DECL_HAS_INIT_PRIORITY_P (decl)
: DECL_STATIC_CONSTRUCTOR (decl));
in.from = decl; in.from = decl;
h = htab_find (init_priority_for_decl, &in); h = htab_find (init_priority_for_decl, &in);
return h ? h->init : DEFAULT_INIT_PRIORITY; return h ? h->init : DEFAULT_INIT_PRIORITY;
...@@ -4323,7 +4320,6 @@ decl_fini_priority_lookup (tree decl) ...@@ -4323,7 +4320,6 @@ decl_fini_priority_lookup (tree decl)
struct tree_map_base in; struct tree_map_base in;
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
gcc_assert (DECL_STATIC_DESTRUCTOR (decl));
in.from = decl; in.from = decl;
h = htab_find (init_priority_for_decl, &in); h = htab_find (init_priority_for_decl, &in);
return h ? h->fini : DEFAULT_INIT_PRIORITY; return h ? h->fini : DEFAULT_INIT_PRIORITY;
......
...@@ -3144,16 +3144,15 @@ extern void decl_fini_priority_insert (tree, priority_type); ...@@ -3144,16 +3144,15 @@ extern void decl_fini_priority_insert (tree, priority_type);
#define DECL_HAS_INIT_PRIORITY_P(NODE) \ #define DECL_HAS_INIT_PRIORITY_P(NODE) \
(VAR_DECL_CHECK (NODE)->decl_with_vis.init_priority_p) (VAR_DECL_CHECK (NODE)->decl_with_vis.init_priority_p)
/* For a VAR_DECL or FUNCTION_DECL with DECL_HAS_INIT_PRIORITY_P set, /* For a VAR_DECL or FUNCTION_DECL the initialization priority of
the initialization priority of NODE. */ NODE. */
#define DECL_INIT_PRIORITY(NODE) \ #define DECL_INIT_PRIORITY(NODE) \
(decl_init_priority_lookup (NODE)) (decl_init_priority_lookup (NODE))
/* Set the initialization priority for NODE to VAL. */ /* Set the initialization priority for NODE to VAL. */
#define SET_DECL_INIT_PRIORITY(NODE, VAL) \ #define SET_DECL_INIT_PRIORITY(NODE, VAL) \
(decl_init_priority_insert (NODE, VAL)) (decl_init_priority_insert (NODE, VAL))
/* For a FUNCTION_DECL with DECL_HAS_INIT_PRIORITY_P set, the /* For a FUNCTION_DECL the finalization priority of NODE. */
finalization priority of NODE. */
#define DECL_FINI_PRIORITY(NODE) \ #define DECL_FINI_PRIORITY(NODE) \
(decl_fini_priority_lookup (NODE)) (decl_fini_priority_lookup (NODE))
/* Set the finalization priority for NODE to VAL. */ /* Set the finalization priority for NODE to VAL. */
......
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