This patch shifts earlier the point during compilation where the rs6000 backend adds decoration to symbols: to encode_section_info.
AIX uses the XCOFF file format, which extends COFF in a few ways, including some increased granularity of sections through a mechanism called Storage Mapping Class -- a decoration for identifiers that maps to a COFF section. Because of the order in which GCC emits symbols and the behavior of the AIX Assembler, the AIX Assembler can see an early reference to an undeclared identifier and create a symbol in the wrong section. The rs6000 backend has been addressing this by emitting storage mapping class decorations on DECLs declared external in OUTPUT_SYMBOL_REF. The rs6000 port replaces the string so that future references also contain the mapping class. This string replacement conflicts with some hash tables so that the port emitted multiple references to the symbol. This patch changes the point at which the mapping class is added and the string is replaced to encode_section_info hook called by make_decl_rtl() and friends. The patch also moves the string management to the stringpool instead of malloc() called by concat(). Bootstrapped on powerpc-ibm-aix7.1.0.0. Thanks, David * config/rs6000/rs6000.c (rs6000_output_symbol_ref): Move storage mapping class decoration from here ... (rs6000_xcoff_encode_section): to here. Index: rs6000.c =================================================================== --- rs6000.c (revision 241237) +++ rs6000.c (working copy) @@ -30667,31 +30668,8 @@ rs6000_xcoff_strip_dollar (const char *name) void rs6000_output_symbol_ref (FILE *file, rtx x) { - /* Currently C++ toc references to vtables can be emitted before it - is decided whether the vtable is public or private. If this is - the case, then the linker will eventually complain that there is - a reference to an unknown section. Thus, for vtables only, - we emit the TOC reference to reference the symbol and not the - section. */ const char *name = XSTR (x, 0); - tree decl = SYMBOL_REF_DECL (x); - if (decl /* sync condition with assemble_external () */ - && DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl) - && (TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL) - && name[strlen (name) - 1] != ']') - { - name = concat (name, - (TREE_CODE (decl) == FUNCTION_DECL - ? "[DS]" : "[UA]"), - NULL); - - /* Don't modify name in extern VAR_DECL to include mapping class. */ - if (TREE_CODE (decl) == FUNCTION_DECL) - XSTR (x, 0) = name; - } - if (VTABLE_NAME_P (name)) { RS6000_OUTPUT_BASENAME (file, name); @@ -35264,6 +35242,7 @@ rs6000_xcoff_encode_section_info (tree decl, rtx r { rtx symbol; int flags; + const char *symname; default_encode_section_info (decl, rtl, first); @@ -35280,6 +35259,28 @@ rs6000_xcoff_encode_section_info (tree decl, rtx r flags &= ~SYMBOL_FLAG_HAS_BLOCK_INFO; SYMBOL_REF_FLAGS (symbol) = flags; + + /* Currently C++ toc references to vtables can be emitted before it + is decided whether the vtable is public or private. If this is + the case, then the linker will eventually complain that there is + a reference to an unknown section. Thus, for vtables only, + we emit the TOC reference to reference the symbol and not the + label identifier. */ + symname = XSTR (symbol, 0); + + if (decl /* sync condition with assemble_external () */ + && DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl) + && ((TREE_CODE (decl) == VAR_DECL && !DECL_THREAD_LOCAL_P (decl)) + || TREE_CODE (decl) == FUNCTION_DECL) + && symname[strlen (symname) - 1] != ']') + { + char *newname = (char *) alloca (strlen (symname) + 5); + strcpy (newname, symname); + strcat (newname, (TREE_CODE (decl) == FUNCTION_DECL + ? "[DS]" : "[UA]")); + XSTR (symbol, 0) = ggc_strdup (newname); + } + } #endif /* HAVE_AS_TLS */ #endif /* TARGET_XCOFF */