On PowerPC64 ELFv1 function symbols are defined on function descriptors in an .opd section rather than in the function code. .opd is not split up by the PowerPC64 backend for comdat groups or other situations where per-function sections are required. Thus SECTION_LINK_ORDER can't use the function name to reference a suitable section for ordering: The .opd section might contain many other function descriptors and they may be in a different order to the final function code placement. This patch arranges to use a code label instead of the function name symbol.
I chose to emit the label inside default_elf_asm_named_section, immediately before the .section directive using the label, and in case someone uses .previous or the like, need to save and restore the current section when switching to the function code section to emit the label. That requires a tweak to switch_to_section in order to get the current section. I checked all the TARGET_ASM_NAMED_SECTION functions and unnamed.callback functions and it appears none will be affected by that tweak. PR target/98125 * varasm.c (default_elf_asm_named_section): Use a function code label rather than the function symbol as the "o" argument. (switch_to_section): Don't set in_section until section directive has been emitted. diff --git a/gcc/varasm.c b/gcc/varasm.c index 97c1e6fff25..5f95f8cfa75 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6866,6 +6866,26 @@ default_elf_asm_named_section (const char *name, unsigned int flags, *f = '\0'; } + char func_label[256]; + if (flags & SECTION_LINK_ORDER) + { + static int recur; + if (recur) + gcc_unreachable (); + else + { + ++recur; + section *save_section = in_section; + static int func_code_labelno; + switch_to_section (function_section (decl)); + ++func_code_labelno; + ASM_GENERATE_INTERNAL_LABEL (func_label, "LPFC", func_code_labelno); + ASM_OUTPUT_LABEL (asm_out_file, func_label); + switch_to_section (save_section); + --recur; + } + } + fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars); /* default_section_type_flags (above) knows which flags need special @@ -6893,11 +6913,8 @@ default_elf_asm_named_section (const char *name, unsigned int flags, fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE); if (flags & SECTION_LINK_ORDER) { - tree id = DECL_ASSEMBLER_NAME (decl); - ultimate_transparent_alias_target (&id); - const char *name = IDENTIFIER_POINTER (id); - name = targetm.strip_name_encoding (name); - fprintf (asm_out_file, ",%s", name); + fputc (',', asm_out_file); + assemble_name_raw (asm_out_file, func_label); } if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE)) { @@ -7821,11 +7838,6 @@ switch_to_section (section *new_section, tree decl) else if (in_section == new_section) return; - if (new_section->common.flags & SECTION_FORGET) - in_section = NULL; - else - in_section = new_section; - switch (SECTION_STYLE (new_section)) { case SECTION_NAMED: @@ -7843,6 +7855,11 @@ switch_to_section (section *new_section, tree decl) break; } + if (new_section->common.flags & SECTION_FORGET) + in_section = NULL; + else + in_section = new_section; + new_section->common.flags |= SECTION_DECLARED; }