Commit 2ce3c6c6 by Jason Merrill Committed by Jason Merrill

tree.h: De-conditionalize init_priority code.

	* tree.h: De-conditionalize init_priority code.
	* mips.h (NM_FLAGS): Change from -Bp to -Bn.
	* collect2.c (NM_FLAGS): Change from -p to -n.
	* configure.in: Turn on collect2 for mipstx39-elf.
	Handle use_collect2=no properly.
	* c-common.c: De-conditionalize init_priority code.
	* collect2.c (extract_init_priority, sort_ids): New fns.
	(main): Call sort_ids.
	Move sequence_number to file scope.
	* configure.in: Handle --enable-init-priority.
	* c-common.c (attrs): Add A_INIT_PRIORITY.
	(init_attributes, decl_attributes): Likewise.
	* tree.h (DEFAULT_INIT_PRIORITY, MAX_INIT_PRIORITY): New macros.
	* tree.c (get_file_function_name_long): Split out...
	(get_file_function_name): ...from here.
cp/:
	* lang-options.h: Add -finit-priority.
	* decl2.c: Likewise.  Check flag_init_priority instead of
	USE_INIT_PRIORITY.
	* decl2.c (setup_initp): New fn.
	(start_objects, finish_objects, do_ctors): Handle init_priority.
	(do_dtors, finish_file): Likewise.

From-SVN: r21701
parent db04386f
Thu Aug 13 17:08:11 1998 Jason Merrill <jason@yorick.cygnus.com>
* tree.h: De-conditionalize init_priority code.
* mips.h (NM_FLAGS): Change from -Bp to -Bn.
* collect2.c (NM_FLAGS): Change from -p to -n.
* configure.in: Turn on collect2 for mipstx39-elf.
Handle use_collect2=no properly.
* c-common.c: De-conditionalize init_priority code.
* collect2.c (extract_init_priority, sort_ids): New fns.
(main): Call sort_ids.
Move sequence_number to file scope.
* configure.in: Handle --enable-init-priority.
* c-common.c (attrs): Add A_INIT_PRIORITY.
(init_attributes, decl_attributes): Likewise.
* tree.h (DEFAULT_INIT_PRIORITY, MAX_INIT_PRIORITY): New macros.
* tree.c (get_file_function_name_long): Split out...
(get_file_function_name): ...from here.
Thu Aug 13 16:09:53 1998 Martin von Loewis <loewis@informatik.hu-berlin.de> Thu Aug 13 16:09:53 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
* expr.c (safe_from_p): Change code to ERROR_MARK only when not * expr.c (safe_from_p): Change code to ERROR_MARK only when not
......
...@@ -52,7 +52,8 @@ int skip_evaluation; ...@@ -52,7 +52,8 @@ int skip_evaluation;
enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION, enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
A_NO_INSTRUMENT_FUNCTION, A_NO_INSTRUMENT_FUNCTION,
A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED, A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS}; A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS,
A_INIT_PRIORITY};
enum format_type { printf_format_type, scanf_format_type, enum format_type { printf_format_type, scanf_format_type,
strftime_format_type }; strftime_format_type };
...@@ -89,6 +90,12 @@ static int if_stack_pointer = 0; ...@@ -89,6 +90,12 @@ static int if_stack_pointer = 0;
/* Generate RTL for the start of an if-then, and record the start of it /* Generate RTL for the start of an if-then, and record the start of it
for ambiguous else detection. */ for ambiguous else detection. */
/* A list of objects which have constructors or destructors which
reside in the global scope, and have an init_priority attribute
associated with them. The decl is stored in the TREE_VALUE slot
and the priority number is stored in the TREE_PURPOSE slot. */
tree static_aggregates_initp;
void void
c_expand_start_cond (cond, exitflag, compstmt_count) c_expand_start_cond (cond, exitflag, compstmt_count)
tree cond; tree cond;
...@@ -383,6 +390,7 @@ init_attributes () ...@@ -383,6 +390,7 @@ init_attributes ()
add_attribute (A_FORMAT_ARG, "format_arg", 1, 1, 1); add_attribute (A_FORMAT_ARG, "format_arg", 1, 1, 1);
add_attribute (A_WEAK, "weak", 0, 0, 1); add_attribute (A_WEAK, "weak", 0, 0, 1);
add_attribute (A_ALIAS, "alias", 1, 1, 1); add_attribute (A_ALIAS, "alias", 1, 1, 1);
add_attribute (A_INIT_PRIORITY, "init_priority", 0, 1, 0);
add_attribute (A_NO_INSTRUMENT_FUNCTION, "no_instrument_function", 0, 0, 1); add_attribute (A_NO_INSTRUMENT_FUNCTION, "no_instrument_function", 0, 0, 1);
} }
...@@ -859,6 +867,62 @@ decl_attributes (node, attributes, prefix_attributes) ...@@ -859,6 +867,62 @@ decl_attributes (node, attributes, prefix_attributes)
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
break; break;
case A_INIT_PRIORITY:
{
tree initp_expr = (args ? TREE_VALUE (args): NULL_TREE);
int pri;
if (initp_expr)
STRIP_NOPS (initp_expr);
if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
{
error ("requested init_priority is not an integer constant");
continue;
}
pri = TREE_INT_CST_LOW (initp_expr);
if (is_type || TREE_CODE (decl) != VAR_DECL
|| ! TREE_STATIC (decl)
|| DECL_EXTERNAL (decl)
|| (TREE_CODE (TREE_TYPE (decl)) != RECORD_TYPE
&& TREE_CODE (TREE_TYPE (decl)) != UNION_TYPE)
/* Static objects in functions are initialized the
first time control passes through that
function. This is not precise enough to pin down an
init_priority value, so don't allow it. */
|| current_function_decl)
{
error ("can only use init_priority attribute on file-scope definitions of objects of class type");
continue;
}
/* Check for init_priorities that are reserved for
implementation. Reserved for language and runtime
support implementations.*/
if ((10 <= pri && pri <= 99)
/* Reserved for standard library implementations. */
|| (500 <= pri && pri <= 999)
/* Reserved for objects with no attributes. */
|| pri > (MAX_INIT_PRIORITY - 50))
{
warning
("requested init_priority is reserved for internal use");
continue;
}
if (pri > MAX_INIT_PRIORITY || pri <= 0)
{
error ("requested init_priority is out of range");
continue;
}
static_aggregates_initp
= perm_tree_cons (initp_expr, decl, static_aggregates_initp);
break;
}
case A_NO_INSTRUMENT_FUNCTION: case A_NO_INSTRUMENT_FUNCTION:
if (TREE_CODE (decl) != FUNCTION_DECL) if (TREE_CODE (decl) != FUNCTION_DECL)
{ {
......
...@@ -137,7 +137,7 @@ extern char *make_temp_file PROTO ((char *)); ...@@ -137,7 +137,7 @@ extern char *make_temp_file PROTO ((char *));
/* Default flags to pass to nm. */ /* Default flags to pass to nm. */
#ifndef NM_FLAGS #ifndef NM_FLAGS
#define NM_FLAGS "-p" #define NM_FLAGS "-n"
#endif #endif
#endif /* OBJECT_FORMAT_NONE */ #endif /* OBJECT_FORMAT_NONE */
...@@ -280,6 +280,8 @@ static void do_wait PROTO((char *)); ...@@ -280,6 +280,8 @@ static void do_wait PROTO((char *));
static void fork_execute PROTO((char *, char **)); static void fork_execute PROTO((char *, char **));
static void maybe_unlink PROTO((char *)); static void maybe_unlink PROTO((char *));
static void add_to_list PROTO((struct head *, char *)); static void add_to_list PROTO((struct head *, char *));
static int extract_init_priority PROTO((char *));
static void sort_ids PROTO((struct head *));
static void write_list PROTO((FILE *, char *, struct id *)); static void write_list PROTO((FILE *, char *, struct id *));
#ifdef COLLECT_EXPORT_LIST #ifdef COLLECT_EXPORT_LIST
static void dump_list PROTO((FILE *, char *, struct id *)); static void dump_list PROTO((FILE *, char *, struct id *));
...@@ -1483,6 +1485,10 @@ main (argc, argv) ...@@ -1483,6 +1485,10 @@ main (argc, argv)
return 0; return 0;
} }
/* Sort ctor and dtor lists by priority. */
sort_ids (&constructors);
sort_ids (&destructors);
maybe_unlink(output_file); maybe_unlink(output_file);
outf = fopen (c_file, "w"); outf = fopen (c_file, "w");
if (outf == (FILE *) 0) if (outf == (FILE *) 0)
...@@ -1697,6 +1703,8 @@ maybe_unlink (file) ...@@ -1697,6 +1703,8 @@ maybe_unlink (file)
} }
static long sequence_number = 0;
/* Add a name to a linked list. */ /* Add a name to a linked list. */
static void static void
...@@ -1707,7 +1715,6 @@ add_to_list (head_ptr, name) ...@@ -1707,7 +1715,6 @@ add_to_list (head_ptr, name)
struct id *newid struct id *newid
= (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1); = (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
struct id *p; struct id *p;
static long sequence_number = 0;
strcpy (newid->name, name); strcpy (newid->name, name);
if (head_ptr->first) if (head_ptr->first)
...@@ -1732,6 +1739,67 @@ add_to_list (head_ptr, name) ...@@ -1732,6 +1739,67 @@ add_to_list (head_ptr, name)
head_ptr->number++; head_ptr->number++;
} }
/* Grab the init priority number from an init function name that
looks like "_GLOBAL_.I.12345.foo". */
static int
extract_init_priority (name)
char *name;
{
int pos = 0;
while (name[pos] == '_')
++pos;
pos += 10; /* strlen ("GLOBAL__X_") */
/* Extract init_p number from ctor/dtor name. */
return strtoul(name + pos, NULL, 10);
}
/* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
ctors will be run from right to left, dtors from left to right. */
static void
sort_ids (head_ptr)
struct head *head_ptr;
{
/* id holds the current element to insert. id_next holds the next
element to insert. id_ptr iterates through the already sorted elements
looking for the place to insert id. */
struct id *id, *id_next, **id_ptr;
int i;
id = head_ptr->first;
/* We don't have any sorted elements yet. */
head_ptr->first = NULL;
for (; id; id = id_next)
{
id_next = id->next;
id->sequence = extract_init_priority (id->name);
for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
if (*id_ptr == NULL
/* If the sequence numbers are the same, we put the id from the
file later on the command line later in the list. */
|| id->sequence > (*id_ptr)->sequence
/* Hack: do lexical compare, too.
|| (id->sequence == (*id_ptr)->sequence
&& strcmp (id->name, (*id_ptr)->name) > 0) */
)
{
id->next = *id_ptr;
*id_ptr = id;
break;
}
}
/* Now set the sequence numbers properly so write_c_file works. */
for (id = head_ptr->first; id; id = id->next)
id->sequence = ++sequence_number;
}
/* Write: `prefix', the names on list LIST, `suffix'. */ /* Write: `prefix', the names on list LIST, `suffix'. */
static void static void
......
...@@ -716,7 +716,7 @@ while (0) ...@@ -716,7 +716,7 @@ while (0)
/* Tell collect what flags to pass to nm. */ /* Tell collect what flags to pass to nm. */
#ifndef NM_FLAGS #ifndef NM_FLAGS
#define NM_FLAGS "-Bp" #define NM_FLAGS "-Bn"
#endif #endif
......
...@@ -130,6 +130,16 @@ AC_ARG_WITH(fast-fixincludes, ...@@ -130,6 +130,16 @@ AC_ARG_WITH(fast-fixincludes,
fast_fixinc="$with_fast_fixincludes", fast_fixinc="$with_fast_fixincludes",
fast_fixinc=no) fast_fixinc=no)
# Enable init_priority.
AC_ARG_ENABLE(init-priority,
[ --enable-init-priority Use attributes to assign initialization order
for static objects.
--disable-init-priority Conform to ISO C++ rules for ordering static objects
(i.e. initialized in order of declaration). ],
if [[[ x$enable_init_priority != xno ]]]; then
extra_c_flags=-DUSE_INIT_PRIORITY
fi)
# Enable threads # Enable threads
# Pass with no value to take the default # Pass with no value to take the default
# Pass with a value to specify a thread package # Pass with a value to specify a thread package
...@@ -2231,6 +2241,8 @@ for machine in $build $host $target; do ...@@ -2231,6 +2241,8 @@ for machine in $build $host $target; do
mipstx39-*-elf*) mipstx39-*-elf*)
tm_file="mips/r3900.h mips/elf.h mips/abi64.h libgloss.h" tm_file="mips/r3900.h mips/elf.h mips/abi64.h libgloss.h"
tmake_file=mips/t-r3900 tmake_file=mips/t-r3900
# FIXME mips-elf should be fixed to use crtstuff.
use_collect2=yes
;; ;;
mips-*-*) # Default MIPS RISC-OS 4.0. mips-*-*) # Default MIPS RISC-OS 4.0.
if [[ x$stabs = xyes ]]; then if [[ x$stabs = xyes ]]; then
...@@ -3323,6 +3335,10 @@ else ...@@ -3323,6 +3335,10 @@ else
done done
fi fi
if [[ x$use_collect2 = xno ]]; then
use_collect2=
fi
# Add a definition of USE_COLLECT2 if system wants one. # Add a definition of USE_COLLECT2 if system wants one.
# Also tell toplev.c what to do. # Also tell toplev.c what to do.
# This substitutes for lots of t-* files. # This substitutes for lots of t-* files.
...@@ -3610,6 +3626,13 @@ if [[ x$enable_haifa != x ]]; then ...@@ -3610,6 +3626,13 @@ if [[ x$enable_haifa != x ]]; then
done done
fi fi
# Warn if using init_priority.
AC_MSG_CHECKING(whether to enable init_priority by default)
if [[ x$enable_init_priority != xyes ]]; then
enable_init_priority=no
fi
AC_MSG_RESULT($enable_init_priority)
# Nothing to do for FLOAT_H, float_format already handled. # Nothing to do for FLOAT_H, float_format already handled.
objdir=`pwd` objdir=`pwd`
AC_SUBST(objdir) AC_SUBST(objdir)
......
1998-08-13 Jason Merrill <jason@yorick.cygnus.com> 1998-08-13 Jason Merrill <jason@yorick.cygnus.com>
* lang-options.h: Add -finit-priority.
* decl2.c: Likewise. Check flag_init_priority instead of
USE_INIT_PRIORITY.
* decl2.c (setup_initp): New fn.
(start_objects, finish_objects, do_ctors): Handle init_priority.
(do_dtors, finish_file): Likewise.
1998-08-13 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (tsubst_copy): Hush warning. * pt.c (tsubst_copy): Hush warning.
* rtti.c (get_tinfo_fn): Also set DECL_IGNORED_P. * rtti.c (get_tinfo_fn): Also set DECL_IGNORED_P.
......
...@@ -173,6 +173,14 @@ int flag_alt_external_templates; ...@@ -173,6 +173,14 @@ int flag_alt_external_templates;
int flag_implicit_templates = 1; int flag_implicit_templates = 1;
/* Nonzero means allow numerical priorities on constructors. */
#ifdef USE_INIT_PRIORITY
int flag_init_priority = 1;
#else
int flag_init_priority;
#endif
/* Nonzero means warn about implicit declarations. */ /* Nonzero means warn about implicit declarations. */
int warn_implicit = 1; int warn_implicit = 1;
...@@ -492,6 +500,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = ...@@ -492,6 +500,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"implement-inlines", &flag_implement_inlines, 1}, {"implement-inlines", &flag_implement_inlines, 1},
{"external-templates", &flag_external_templates, 1}, {"external-templates", &flag_external_templates, 1},
{"implicit-templates", &flag_implicit_templates, 1}, {"implicit-templates", &flag_implicit_templates, 1},
{"init-priority", &flag_init_priority, 1},
{"huge-objects", &flag_huge_objects, 1}, {"huge-objects", &flag_huge_objects, 1},
{"conserve-space", &flag_conserve_space, 1}, {"conserve-space", &flag_conserve_space, 1},
{"vtable-thunks", &flag_vtable_thunks, 1}, {"vtable-thunks", &flag_vtable_thunks, 1},
...@@ -2929,18 +2938,104 @@ get_sentry (base) ...@@ -2929,18 +2938,104 @@ get_sentry (base)
return sentry; return sentry;
} }
/* A list of objects which have constructors or destructors
which reside in the global scope. The decl is stored in
the TREE_VALUE slot and the initializer is stored
in the TREE_PURPOSE slot. */
extern tree static_aggregates_initp;
/* Set up the static_aggregates* lists for processing. Subroutine of
finish_file. Note that this function changes the format of
static_aggregates_initp, from (priority . decl) to
(priority . ((initializer . decl) ...)). */
static void
setup_initp ()
{
tree t, *p, next_t;
if (! flag_init_priority)
{
for (t = static_aggregates_initp; t; t = TREE_CHAIN (t))
cp_warning ("init_priority for `%#D' ignored without -finit-priority",
TREE_VALUE (t));
return;
}
/* First, remove any entries from static_aggregates that are also in
static_aggregates_initp, and update the entries in _initp to
include the initializer. */
p = &static_aggregates;
for (; *p; )
{
t = value_member (TREE_VALUE (*p), static_aggregates_initp);
if (t)
{
TREE_VALUE (t) = *p;
*p = TREE_CHAIN (*p);
TREE_CHAIN (TREE_VALUE (t)) = NULL_TREE;
}
else
p = &TREE_CHAIN (*p);
}
/* Then, group static_aggregates_initp. After this step, there will only
be one entry for each priority, with a chain coming off it. */
t = static_aggregates_initp;
static_aggregates_initp = NULL_TREE;
for (; t; t = next_t)
{
next_t = TREE_CHAIN (t);
for (p = &static_aggregates_initp; ; p = &TREE_CHAIN (*p))
{
if (*p == NULL_TREE
|| tree_int_cst_lt (TREE_PURPOSE (*p), TREE_PURPOSE (t)))
{
TREE_CHAIN (t) = *p;
*p = t;
break;
}
else if (tree_int_cst_equal (TREE_PURPOSE (*p), TREE_PURPOSE (t)))
{
TREE_CHAIN (TREE_VALUE (t)) = TREE_VALUE (*p);
TREE_VALUE (*p) = TREE_VALUE (t);
break;
}
}
}
/* Reverse each list to preserve the order (currently reverse declaration
order, for destructors). */
for (t = static_aggregates_initp; t; t = TREE_CHAIN (t))
TREE_VALUE (t) = nreverse (TREE_VALUE (t));
}
/* Start the process of running a particular set of global constructors /* Start the process of running a particular set of global constructors
or destructors. Subroutine of do_[cd]tors. */ or destructors. Subroutine of do_[cd]tors. */
static void static void
start_objects (method_type) start_objects (method_type, initp)
int method_type; int method_type, initp;
{ {
tree fnname; tree fnname;
char type[10];
/* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */ /* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
fnname = get_file_function_name (method_type); if (flag_init_priority)
{
if (initp == 0)
initp = DEFAULT_INIT_PRIORITY;
sprintf (type, "%c%c%.5u", method_type, JOINER, initp);
}
else
sprintf (type, "%c", method_type);
fnname = get_file_function_name_long (type);
start_function (void_list_node, start_function (void_list_node,
make_call_declarator (fnname, void_list_node, NULL_TREE, make_call_declarator (fnname, void_list_node, NULL_TREE,
...@@ -2958,18 +3053,21 @@ start_objects (method_type) ...@@ -2958,18 +3053,21 @@ start_objects (method_type)
or destructors. Subroutine of do_[cd]tors. */ or destructors. Subroutine of do_[cd]tors. */
static void static void
finish_objects (method_type) finish_objects (method_type, initp)
int method_type; int method_type, initp;
{ {
char *fnname; char *fnname;
tree list = (method_type == 'I' ? static_ctors : static_dtors); if (! initp)
{
tree list = (method_type == 'I' ? static_ctors : static_dtors);
if (! current_function_decl && list) if (! current_function_decl && list)
start_objects (method_type); start_objects (method_type, initp);
for (; list; list = TREE_CHAIN (list)) for (; list; list = TREE_CHAIN (list))
expand_expr_stmt (build_function_call (TREE_VALUE (list), NULL_TREE)); expand_expr_stmt (build_function_call (TREE_VALUE (list), NULL_TREE));
}
if (! current_function_decl) if (! current_function_decl)
return; return;
...@@ -2982,19 +3080,56 @@ finish_objects (method_type) ...@@ -2982,19 +3080,56 @@ finish_objects (method_type)
pop_momentary (); pop_momentary ();
finish_function (lineno, 0, 0); finish_function (lineno, 0, 0);
if (method_type == 'I') if (! flag_init_priority)
assemble_constructor (fnname); {
else if (method_type == 'I')
assemble_destructor (fnname); assemble_constructor (fnname);
else
assemble_destructor (fnname);
}
#ifdef ASM_OUTPUT_SECTION_NAME
/* If we're using init priority we can't use assemble_*tor, but on ELF
targets we can stick the references into named sections for GNU ld
to collect. */
if (flag_init_priority)
{
char buf[15];
if (initp == 0)
initp = DEFAULT_INIT_PRIORITY;
sprintf (buf, ".%ctors.%.5u", method_type == 'I' ? 'c' : 'd',
/* invert the numbering so the linker puts us in the proper
order; constructors are run from right to left, and the
linker sorts in increasing order. */
MAX_INIT_PRIORITY - initp);
named_section (NULL_TREE, buf, 0);
assemble_integer (gen_rtx_SYMBOL_REF (Pmode, fnname),
POINTER_SIZE / BITS_PER_UNIT, 1);
}
#endif
} }
/* Generate a function to run a set of global destructors. Subroutine of /* Generate a function to run a set of global destructors. START is either
finish_file. */ NULL_TREE or a node indicating a set of destructors with the same
init priority. Subroutine of finish_file. */
static void static void
do_dtors () do_dtors (start)
tree start;
{ {
tree vars = static_aggregates; tree vars;
int initp;
if (start)
{
initp = TREE_INT_CST_LOW (TREE_PURPOSE (start));
vars = TREE_VALUE (start);
}
else
{
initp = 0;
vars = static_aggregates;
}
for (; vars; vars = TREE_CHAIN (vars)) for (; vars; vars = TREE_CHAIN (vars))
{ {
...@@ -3010,7 +3145,7 @@ do_dtors () ...@@ -3010,7 +3145,7 @@ do_dtors ()
|| DECL_WEAK (decl))); || DECL_WEAK (decl)));
if (! current_function_decl) if (! current_function_decl)
start_objects ('D'); start_objects ('D', initp);
/* Because of: /* Because of:
...@@ -3053,16 +3188,30 @@ do_dtors () ...@@ -3053,16 +3188,30 @@ do_dtors ()
} }
} }
finish_objects ('D'); finish_objects ('D', initp);
} }
/* Generate a function to run a set of global constructors. Subroutine of /* Generate a function to run a set of global constructors. START is
finish_file. */ either NULL_TREE or a node indicating a set of constructors with the
same init priority. Subroutine of finish_file. */
static void static void
do_ctors () do_ctors (start)
tree start;
{ {
tree vars = static_aggregates; tree vars;
int initp;
if (start)
{
initp = TREE_INT_CST_LOW (TREE_PURPOSE (start));
vars = TREE_VALUE (start);
}
else
{
initp = 0;
vars = static_aggregates;
}
/* Reverse the list so it's in the right order for ctors. */ /* Reverse the list so it's in the right order for ctors. */
vars = nreverse (vars); vars = nreverse (vars);
...@@ -3088,7 +3237,7 @@ do_ctors () ...@@ -3088,7 +3237,7 @@ do_ctors ()
|| DECL_WEAK (decl))); || DECL_WEAK (decl)));
if (! current_function_decl) if (! current_function_decl)
start_objects ('I'); start_objects ('I', initp);
/* Set these global variables so that GDB at least puts /* Set these global variables so that GDB at least puts
us near the declaration which required the initialization. */ us near the declaration which required the initialization. */
...@@ -3148,7 +3297,7 @@ do_ctors () ...@@ -3148,7 +3297,7 @@ do_ctors ()
my_friendly_abort (22); my_friendly_abort (22);
} }
finish_objects ('I'); finish_objects ('I', initp);
} }
/* This routine is called from the last rule in yyparse (). /* This routine is called from the last rule in yyparse ().
...@@ -3262,17 +3411,28 @@ finish_file () ...@@ -3262,17 +3411,28 @@ finish_file ()
if (static_dtors || vars) if (static_dtors || vars)
needs_cleaning = 1; needs_cleaning = 1;
/* The aggregates are listed in reverse declaration order, for cleaning. */ setup_initp ();
/* After setup_initp, the aggregates are listed in reverse declaration
order, for cleaning. */
if (needs_cleaning) if (needs_cleaning)
{ {
do_dtors (); do_dtors (NULL_TREE);
if (flag_init_priority)
for (vars = static_aggregates_initp; vars; vars = TREE_CHAIN (vars))
do_dtors (vars);
} }
/* do_ctors will reverse the lists for messing up. */ /* do_ctors will reverse the lists for messing up. */
if (needs_messing_up) if (needs_messing_up)
{ {
do_ctors (); do_ctors (NULL_TREE);
}
if (flag_init_priority)
for (vars = static_aggregates_initp; vars; vars = TREE_CHAIN (vars))
do_ctors (vars);
}
permanent_allocation (1); permanent_allocation (1);
......
...@@ -66,6 +66,8 @@ DEFINE_LANG_NAME ("C++") ...@@ -66,6 +66,8 @@ DEFINE_LANG_NAME ("C++")
{ "-fno-implement-inlines", "Export functions even if they can be inlined" }, { "-fno-implement-inlines", "Export functions even if they can be inlined" },
{ "-fimplicit-templates", "Emit implicit instatiations if needed" }, { "-fimplicit-templates", "Emit implicit instatiations if needed" },
{ "-fno-implicit-templates", "" }, { "-fno-implicit-templates", "" },
{ "-finit-priority", "Handle the init_priority attribute" },
{ "-fno-init-priority", "" },
{ "-flabels-ok", "Labels can be used as first class objects" }, { "-flabels-ok", "Labels can be used as first class objects" },
{ "-fno-labels-ok", "" }, { "-fno-labels-ok", "" },
{ "-fmemoize-lookups", "Enable caching of member function resolutions" }, { "-fmemoize-lookups", "Enable caching of member function resolutions" },
......
...@@ -1030,6 +1030,11 @@ your code with this flag (including the C++ library, if you use it). ...@@ -1030,6 +1030,11 @@ your code with this flag (including the C++ library, if you use it).
This flag is not useful when compiling with -fvtable-thunks. This flag is not useful when compiling with -fvtable-thunks.
@item -finit-priority
Support @samp{__attribute__ ((init_priority (n)))} for controlling the
order of initialization of file-scope objects. On ELF targets, this
requires GNU ld 2.10 or later.
@item -fno-implement-inlines @item -fno-implement-inlines
To save space, do not emit out-of-line copies of inline functions To save space, do not emit out-of-line copies of inline functions
controlled by @samp{#pragma implementation}. This will cause linker controlled by @samp{#pragma implementation}. This will cause linker
......
...@@ -4806,24 +4806,24 @@ dump_tree_statistics () ...@@ -4806,24 +4806,24 @@ dump_tree_statistics ()
#define FILE_FUNCTION_PREFIX_LEN 9 #define FILE_FUNCTION_PREFIX_LEN 9
#ifndef NO_DOLLAR_IN_LABEL #ifndef NO_DOLLAR_IN_LABEL
#define FILE_FUNCTION_FORMAT "_GLOBAL_$D$%s" #define FILE_FUNCTION_FORMAT "_GLOBAL_$%s$%s"
#else /* NO_DOLLAR_IN_LABEL */ #else /* NO_DOLLAR_IN_LABEL */
#ifndef NO_DOT_IN_LABEL #ifndef NO_DOT_IN_LABEL
#define FILE_FUNCTION_FORMAT "_GLOBAL_.D.%s" #define FILE_FUNCTION_FORMAT "_GLOBAL_.%s.%s"
#else /* NO_DOT_IN_LABEL */ #else /* NO_DOT_IN_LABEL */
#define FILE_FUNCTION_FORMAT "_GLOBAL__D_%s" #define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s"
#endif /* NO_DOT_IN_LABEL */ #endif /* NO_DOT_IN_LABEL */
#endif /* NO_DOLLAR_IN_LABEL */ #endif /* NO_DOLLAR_IN_LABEL */
extern char * first_global_object_name; extern char * first_global_object_name;
extern char * weak_global_object_name; extern char * weak_global_object_name;
/* If KIND=='I', return a suitable global initializer (constructor) name. /* TYPE is some string to identify this function to the linker or
If KIND=='D', return a suitable global clean-up (destructor) name. */ collect2. */
tree tree
get_file_function_name (kind) get_file_function_name_long (type)
int kind; char *type;
{ {
char *buf; char *buf;
register char *p; register char *p;
...@@ -4837,13 +4837,14 @@ get_file_function_name (kind) ...@@ -4837,13 +4837,14 @@ get_file_function_name (kind)
else else
p = input_filename; p = input_filename;
buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)); buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
+ strlen (type));
/* Set up the name of the file-level functions we may need. */ /* Set up the name of the file-level functions we may need. */
/* Use a global object (which is already required to be unique over /* Use a global object (which is already required to be unique over
the program) rather than the file name (which imposes extra the program) rather than the file name (which imposes extra
constraints). -- Raeburn@MIT.EDU, 10 Jan 1990. */ constraints). -- Raeburn@MIT.EDU, 10 Jan 1990. */
sprintf (buf, FILE_FUNCTION_FORMAT, p); sprintf (buf, FILE_FUNCTION_FORMAT, type, p);
/* Don't need to pull weird characters out of global names. */ /* Don't need to pull weird characters out of global names. */
if (p != first_global_object_name) if (p != first_global_object_name)
...@@ -4866,10 +4867,23 @@ get_file_function_name (kind) ...@@ -4866,10 +4867,23 @@ get_file_function_name (kind)
*p = '_'; *p = '_';
} }
buf[FILE_FUNCTION_PREFIX_LEN] = kind;
return get_identifier (buf); return get_identifier (buf);
} }
/* If KIND=='I', return a suitable global initializer (constructor) name.
If KIND=='D', return a suitable global clean-up (destructor) name. */
tree
get_file_function_name (kind)
int kind;
{
char p[2];
p[0] = kind;
p[1] = 0;
return get_file_function_name_long (p);
}
/* Expand (the constant part of) a SET_TYPE CONSTRUCTOR node. /* Expand (the constant part of) a SET_TYPE CONSTRUCTOR node.
The result is placed in BUFFER (which has length BIT_SIZE), The result is placed in BUFFER (which has length BIT_SIZE),
......
...@@ -1124,6 +1124,11 @@ struct tree_type ...@@ -1124,6 +1124,11 @@ struct tree_type
do not allocate storage, and refer to a definition elsewhere. */ do not allocate storage, and refer to a definition elsewhere. */
#define DECL_EXTERNAL(NODE) (DECL_CHECK (NODE)->decl.external_flag) #define DECL_EXTERNAL(NODE) (DECL_CHECK (NODE)->decl.external_flag)
/* In a VAR_DECL for a RECORD_TYPE, sets number for non-init_priority
initializatons. */
#define DEFAULT_INIT_PRIORITY 65535
#define MAX_INIT_PRIORITY 65535
/* In a TYPE_DECL /* In a TYPE_DECL
nonzero means the detail info about this type is not dumped into stabs. nonzero means the detail info about this type is not dumped into stabs.
Instead it will generate cross reference ('x') of names. Instead it will generate cross reference ('x') of names.
...@@ -1843,6 +1848,7 @@ extern void (*incomplete_decl_finalize_hook) PROTO((tree)); ...@@ -1843,6 +1848,7 @@ extern void (*incomplete_decl_finalize_hook) PROTO((tree));
/* In tree.c */ /* In tree.c */
extern char *perm_calloc PROTO((int, long)); extern char *perm_calloc PROTO((int, long));
extern tree get_file_function_name PROTO((int)); extern tree get_file_function_name PROTO((int));
extern tree get_file_function_name_long PROTO((char *));
extern tree get_set_constructor_bits PROTO((tree, char *, int)); extern tree get_set_constructor_bits PROTO((tree, char *, int));
extern tree get_set_constructor_bytes PROTO((tree, extern tree get_set_constructor_bytes PROTO((tree,
unsigned char *, int)); unsigned char *, int));
......
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