diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ab3a41e46d1..9bff84f653c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2005-01-16 John David Anglin + + PR target/16304 + * defaults.h (TARGET_DEFERRED_OUTPUT_DEFS): Provide default. + * toplev.c (compile_file): Call process_pending_assemble_output_defs + just before targetm.asm_out.file_end. + * tree.h (process_pending_assemble_output_defs): Declare. + * varasm.c (assemble_output_def, process_pending_assemble_output_defs): + New functions. + (assemble_alias): Defer generation of assembly code for defines when + TARGET_DEFERRED_OUTPUT_DEFS is true. + * config/rs6000/aix41.h (TARGET_DEFERRED_OUTPUT_DEFS): Define. + * config/rs6000/aix43.h (TARGET_DEFERRED_OUTPUT_DEFS): Define. + * doc/tm.texi (TARGET_DEFERRED_OUTPUT_DEFS): document. + 2005-01-15 John David Anglin PR target/19336 diff --git a/gcc/config/rs6000/aix41.h b/gcc/config/rs6000/aix41.h index bdf1fe6cd7a..74afa7a875d 100644 --- a/gcc/config/rs6000/aix41.h +++ b/gcc/config/rs6000/aix41.h @@ -91,3 +91,7 @@ #undef RS6000_CALL_GLUE #define RS6000_CALL_GLUE "{cror 31,31,31|nop}" +/* The IBM AIX 4.x assembler doesn't support forward references in + .set directives. We handle this by deferring the output of .set + directives to the end of the compilation unit. */ +#define TARGET_DEFERRED_OUTPUT_DEFS(DECL,TARGET) true diff --git a/gcc/config/rs6000/aix43.h b/gcc/config/rs6000/aix43.h index e7de00f75a6..4eae08a5855 100644 --- a/gcc/config/rs6000/aix43.h +++ b/gcc/config/rs6000/aix43.h @@ -181,3 +181,8 @@ do { \ #undef LD_INIT_SWITCH #define LD_INIT_SWITCH "-binitfini" + +/* The IBM AIX 4.x assembler doesn't support forward references in + .set directives. We handle this by deferring the output of .set + directives to the end of the compilation unit. */ +#define TARGET_DEFERRED_OUTPUT_DEFS(DECL,TARGET) true diff --git a/gcc/defaults.h b/gcc/defaults.h index 236ed90dee0..8d342b927a0 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -137,6 +137,12 @@ do { fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \ #endif #endif +/* Decide whether to defer emitting the assembler output for an equate + of two values. The default is to not defer output. */ +#ifndef TARGET_DEFERRED_OUTPUT_DEFS +#define TARGET_DEFERRED_OUTPUT_DEFS(DECL,TARGET) false +#endif + /* This is how to output the definition of a user-level label named NAME, such as the label on a static function or variable NAME. */ diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 52cb78b1e89..c842b05232c 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -7045,6 +7045,15 @@ If @code{SET_ASM_OP} is defined, a default definition is provided which is correct for most systems. @end defmac +@defmac TARGET_DEFERRED_OUTPUT_DEFS (@var{decl_of_name}, @var{decl_of_value}) +A C statement that evaluates to true if the assembler code which defines +(equates) the symbol whose tree node is @var{decl_of_name} to have the value +of the tree node @var{decl_of_value} should be emitted near the end of the +current compilation unit. The default is to not defer output of defines. +This macro affects defines output by @samp{ASM_OUTPUT_DEF} and +@samp{ASM_OUTPUT_DEF_FROM_DECLS}. +@end defmac + @defmac ASM_OUTPUT_WEAK_ALIAS (@var{stream}, @var{name}, @var{value}) A C statement to output to the stdio stream @var{stream} assembler code which defines (equates) the weak symbol @var{name} to have the value diff --git a/gcc/toplev.c b/gcc/toplev.c index c403b110fd2..8ef19f773ea 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1043,6 +1043,9 @@ compile_file (void) expander can also generate them. */ process_pending_assemble_externals (); + /* Flush any pending equate directives. */ + process_pending_assemble_output_defs (); + /* Attach a special .ident directive to the end of the file to identify the version of GCC which compiled this code. The format of the .ident string is patterned after the ones produced by native SVR4 compilers. */ diff --git a/gcc/tree.h b/gcc/tree.h index f3410c6de6f..4fdff0c76e1 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3703,6 +3703,7 @@ extern void mark_decl_referenced (tree); extern void notice_global_symbol (tree); extern void set_user_assembler_name (tree, const char *); extern void process_pending_assemble_externals (void); +extern void process_pending_assemble_output_defs (void); /* In stmt.c */ extern void expand_computed_goto (tree); diff --git a/gcc/varasm.c b/gcc/varasm.c index 8252f0e123f..d37bee89734 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -4347,20 +4347,67 @@ globalize_decl (tree decl) targetm.asm_out.globalize_label (asm_out_file, name); } +/* Some targets do not allow a forward or undefined reference in a + ASM_OUTPUT_DEF. Thus, a mechanism is needed to defer the output of + this assembler code. The following struct holds the declaration + and target for a deferred output define. */ +struct output_def_pair GTY(()) +{ + tree decl; + tree target; +}; +typedef struct output_def_pair *output_def_pair; + +/* Define gc'd vector type. */ +DEF_VEC_GC_P(output_def_pair); + +/* Vector of output_def_pair pointers. */ +static GTY(()) VEC(output_def_pair) *output_defs; + +#ifdef ASM_OUTPUT_DEF +/* Output the assembler code for a define (equate) using ASM_OUTPUT_DEF + or ASM_OUTPUT_DEF_FROM_DECLS. The function defines the symbol whose + tree node is DECL to have the value of the tree node TARGET. */ + +static void +assemble_output_def (tree decl ATTRIBUTE_UNUSED, tree target ATTRIBUTE_UNUSED) +{ +#ifdef ASM_OUTPUT_DEF_FROM_DECLS + ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target); +#else + ASM_OUTPUT_DEF (asm_out_file, + IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), + IDENTIFIER_POINTER (target)); +#endif +} +#endif + +/* Process the vector of pending assembler defines. */ + +void +process_pending_assemble_output_defs (void) +{ +#ifdef ASM_OUTPUT_DEF + unsigned i; + output_def_pair p; + + for (i = 0; VEC_iterate (output_def_pair, output_defs, i, p); i++) + assemble_output_def (p->decl, p->target); + + output_defs = NULL; +#endif +} + /* Emit an assembler directive to make the symbol for DECL an alias to the symbol for TARGET. */ void assemble_alias (tree decl, tree target) { - const char *name; - /* We must force creation of DECL_RTL for debug info generation, even though we don't use it here. */ make_decl_rtl (decl); - name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - #ifdef ASM_OUTPUT_DEF /* Make name accessible from other files, if appropriate. */ @@ -4370,16 +4417,25 @@ assemble_alias (tree decl, tree target) maybe_assemble_visibility (decl); } -#ifdef ASM_OUTPUT_DEF_FROM_DECLS - ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target); -#else - ASM_OUTPUT_DEF (asm_out_file, name, IDENTIFIER_POINTER (target)); -#endif + if (TARGET_DEFERRED_OUTPUT_DEFS (decl, target)) + { + output_def_pair p; + + p = ggc_alloc (sizeof (struct output_def_pair)); + p->decl = decl; + p->target = target; + VEC_safe_push (output_def_pair, output_defs, p); + } + else + assemble_output_def (decl, target); #else /* !ASM_OUTPUT_DEF */ #if defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL) if (DECL_WEAK (decl)) { + const char *name; tree *p, t; + + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); #ifdef ASM_WEAKEN_DECL ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target)); #else