diff mbox

[rs6000] ELFv2 ABI 2/8: Remove function descriptors

Message ID 201311111441.rABEfnNS007209@d06av02.portsmouth.uk.ibm.com
State New
Headers show

Commit Message

Ulrich Weigand Nov. 11, 2013, 2:41 p.m. UTC
Hello,

this patch adds the first major feature of the ELFv2 ABI: removal
of function descriptors.


In the current ABI, it is the responsibility of a caller to set
up the TOC pointer needed by the callee by loading the correct
value into r2.  This typically happens in one of these ways:

- For a direct function call within the same module, caller and
  callee share the same TOC, so r2 already contains the correct
  value.

- For a direct function call to a function in another module,
  the linker will interpose a PLT stub which reloads r2 to be
  appropriate for the callee, with help from ld.so.

- For an indirect function call, the "function pointer" points
  to function descriptor that holds the target function address
  as well as the appropriate TOC value (and a static chain
  value for nested functions).  The caller must load those
  values up before transfering control to the callee.


With the new ABI, it is the responsibility of the callee to
set up its own TOC pointer.  This has a number of advantages,
in particular for a callee that doesn't actually need a TOC,
and makes the function pointer call sequence more effective
by avoiding pipeline hazards.

However, it remains true that with the PowerPC ISA, it is
difficult to actually establish addressability to the TOC
without any outside help.  To avoid introducing new performance
regressions, the new ABI instead provides a dual entry point
scheme.

Any function that needs a TOC may provide two entry points:

- The first ("global") entry point is intended to called via
  indirect calls.  It expects r12 to be set up to point to
  the entry point address itself.  (Since in order to perform
  an indirect call, the address must be loaded into some GPR
  anyway, this does not impose a substantial impact on the
  caller ...)  Code at the global entry point is expected
  to load up r2 with the appropriate TOC value for this
  function (and it may use the r12 value to compute that),
  and then fall through to the local entry point.

- The second ("local") entry point expects r2 to be set up
  to the current TOC, much like an entry point in the current
  ABI does.  However, it must not expect r12 to hold any
  particular value.  This means that a local direct function
  call within the same module can be done via a simple "bl"
  instruction just as today.  Note that the linker will
  automatically direct a "bl func" to the *local* entry
  point associated with the symbol "func"; not the global one.

If local and global entry points coincide, the function may
expect no particular value in either r12 or r2; this can be
used by functions that do not need a TOC.

There exists just one single ELF symbol for both local and
global entry points; its symbol value refers to the global
entry point, and flag bits in ELF st_other encode the
offset from there to the local entry point.  The compiler
emits a .localentry directive to announce this location
to the assembler, which will encode it as appropriate.


This patch implements all aspects needed for this scheme:

- Emit ".abiversion 2" assembler directive to help the assembler
  and linker understand the ABI implemented in this file.
- Remove all handling of function descriptors / .opd section /
  dot symbols for the ELFv2 ABI.
- Output a global entry point prologue and local entry point
  marker for functions that use the TOC.
- Implement the ELFv2 function pointer call sequence.
- Use trampolines to handle nested functions, just like on
  32-bit (including marking the stack as executable).
- No longer scan for the old ABI indirect call sequence in
  linux-unwind.h.
- Update assembler code to the new ABI:
   - gcc/config/rs6000/ppc-asm.h (used by libgcc and elsewhere)
   - lititm/config/powerpc/sjlj.S
   - gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c

In addition, some related changes are necessary:

- Move the code generating the call to _mcount for -mprofile-kernel
  from output_function_profiler to rs6000_output_function_prologue,
  since this call must happen at the local entry point, not the
  global entry point.
- Disable (now useless) tests for -mpointers-to-nested-functions.
- Fix the libstc++ extract_symvers.in script to ignore markers
  emitted by readelf --symbols that indicate local entry points.
- Fix the "gotest" script to no longer expect function symbols
  to reside in the data segment.  (I understand this last bit
  needs to go into the Go repository first ...)

Bye,
Ulrich


gcc/ChangeLog:

2013-11-11  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

	* config/rs6000/rs6000.c (machine_function): New member
	r2_setup_needed.
	(rs6000_emit_prologue): Set r2_setup_needed if necessary.
	(rs6000_output_mi_thunk): Set r2_setup_needed.
	(rs6000_output_function_prologue): Output global entry point
	prologue and local entry point marker if needed for ABI_ELFv2.
	Output -mprofile-kernel code here.
	(output_function_profiler): Do not output -mprofile-kernel
	code here; moved to rs6000_output_function_prologue.
	(rs6000_file_start): Output ".abiversion 2" for ABI_ELFv2.

	(rs6000_emit_move): Do not handle dot symbols for ABI_ELFv2.
	(rs6000_output_function_entry): Likewise.
	(rs6000_assemble_integer): Likewise.
	(rs6000_elf_encode_section_info): Likewise.
	(rs6000_elf_declare_function_name): Do not create dot symbols
	or .opd section for ABI_ELFv2.

	(rs6000_trampoline_size): Update for ABI_ELFv2 trampolines.
	(rs6000_trampoline_init): Likewise.
	(rs6000_elf_file_end): Call file_end_indicate_exec_stack
	for ABI_ELFv2.

	(rs6000_call_aix): Handle ELFv2 indirect calls.  Do not check
	for function descriptors in ABI_ELFv2.

	* config/rs6000/rs6000.md ("*call_indirect_aix<mode>"): Support
	on ABI_AIX only, not ABI_ELFv2.
	("*call_value_indirect_aix<mode>"): Likewise.
	("*call_indirect_elfv2<mode>"): New pattern.
	("*call_value_indirect_elfv2<mode>"): Likewise.

	* config/rs6000/predicates.md ("symbol_ref_operand"): Do not
	check for function descriptors in ABI_ELFv2.
	("current_file_function_operand"): Likewise.

	* config/rs6000/ppc-asm.h [__powerpc64__ && _CALL_ELF == 2]:
	(toc): Undefine.
	(FUNC_NAME): Define ELFv2 variant.
	(JUMP_TARGET): Likewise.
	(FUNC_START): Likewise.
	(HIDDEN_FUNC): Likewise.
	(FUNC_END): Likeiwse.

libitm/ChangeLog:

2013-11-11  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

	* config/powerpc/sjlj.S [__powerpc64__ && _CALL_ELF == 2]:
	(FUNC): Define ELFv2 variant.
	(END): Likewise.
	(HIDDEN): Likewise.
	(CALL): Likewise.
	(BASE): Likewise.
	(LR_SAVE): Likewise.

libgcc/ChangeLog:

2013-11-11  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
	    Alan Modra  <amodra@gmail.com>

	* config/rs6000/tramp.S [__powerpc64__ && _CALL_ELF == 2]:
	(trampoline_initial): Provide ELFv2 variant.
	(__trampoline_setup): Likewise.

	* config/rs6000/linux-unwind.h (frob_update_context): Do not
	check for AIX indirect function call sequence if _CALL_ELF == 2.

gcc/testsuite/ChangeLog:

2013-11-11  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

	* gcc.target/powerpc/ppc64-abi-dfp-1.c (FUNC_START): New macro.
	(WRAPPER): Use it.
	* gcc.target/powerpc/no-r11-1.c: Skip on powerpc_elfv2.
	* gcc.target/powerpc/no-r11-2.c: Skip on powerpc_elfv2.
	* gcc.target/powerpc/no-r11-3.c: Skip on powerpc_elfv2.

libstdc++/ChangeLog:

2013-11-11  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

	* scripts/extract_symvers.in: Ignore <localentry: > fields
	in readelf --symbols output.
diff mbox

Patch

Index: gcc/gcc/config/rs6000/rs6000.c
===================================================================
--- gcc.orig/gcc/config/rs6000/rs6000.c
+++ gcc/gcc/config/rs6000/rs6000.c
@@ -140,6 +140,8 @@  typedef struct GTY(()) machine_function
      64-bits wide and is allocated early enough so that the offset
      does not overflow the 16-bit load/store offset field.  */
   rtx sdmode_stack_slot;
+  /* Flag if r2 setup is needed with ELFv2 ABI.  */
+  bool r2_setup_needed;
 } machine_function;
 
 /* Support targetm.vectorize.builtin_mask_for_load.  */
@@ -4762,6 +4764,9 @@  rs6000_file_start (void)
 	putc ('\n', file);
     }
 
+  if (DEFAULT_ABI == ABI_ELFv2)
+    fprintf (file, "\t.abiversion 2\n");
+
   if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2
       || (TARGET_ELF && flag_pic == 2))
     {
@@ -8282,7 +8287,7 @@  rs6000_emit_move (rtx dest, rtx source, 
 
 	  /* If this is a function address on -mcall-aixdesc,
 	     convert it to the address of the descriptor.  */
-	  if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+	  if (DEFAULT_ABI == ABI_AIX
 	      && GET_CODE (operands[1]) == SYMBOL_REF
 	      && XSTR (operands[1], 0)[0] == '.')
 	    {
@@ -16678,13 +16683,13 @@  rs6000_output_function_entry (FILE *file
 	  gcc_unreachable ();
 
 	case ABI_AIX:
-	case ABI_ELFv2:
 	  if (DOT_SYMBOLS)
 	    putc ('.', file);
 	  else
 	    ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "L.");
 	  break;
 
+	case ABI_ELFv2:
 	case ABI_V4:
 	case ABI_DARWIN:
 	  break;
@@ -17482,7 +17487,7 @@  rs6000_assemble_integer (rtx x, unsigned
 	 itself.  */
       else if (GET_CODE (x) == SYMBOL_REF
 	       && XSTR (x, 0)[0] == '.'
-	       && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2))
+	       && DEFAULT_ABI == ABI_AIX)
 	{
 	  const char *name = XSTR (x, 0);
 	  while (*name == '.')
@@ -21582,6 +21587,17 @@  rs6000_emit_prologue (void)
 #define NOT_INUSE(R) do {} while (0)
 #endif
 
+  if (DEFAULT_ABI == ABI_ELFv2)
+    {
+      cfun->machine->r2_setup_needed = df_regs_ever_live_p (TOC_REGNUM);
+
+      /* With -mminimal-toc we may generate an extra use of r2 below.  */
+      if (!TARGET_SINGLE_PIC_BASE
+	  && TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
+	cfun->machine->r2_setup_needed = true;
+    }
+
+
   if (flag_stack_usage_info)
     current_function_static_stack_size = info->total_size;
 
@@ -22458,6 +22474,45 @@  rs6000_output_function_prologue (FILE *f
 	}
     }
 
+  /* ELFv2 ABI r2 setup code and local entry point.  This must follow
+     immediately after the global entry point label.  */
+  if (DEFAULT_ABI == ABI_ELFv2 && cfun->machine->r2_setup_needed)
+    {
+      const char *name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+
+      fprintf (file, "0:\taddis 2,12,.TOC.-0b@ha\n");
+      fprintf (file, "\taddi 2,2,.TOC.-0b@l\n");
+
+      fputs ("\t.localentry\t", file);
+      assemble_name (file, name);
+      fputs (",.-", file);
+      assemble_name (file, name);
+      fputs ("\n", file);
+    }
+
+  /* Output -mprofile-kernel code.  This needs to be done here instead of
+     in output_function_profile since it must go after the ELFv2 ABI
+     local entry point.  */
+  if (TARGET_PROFILE_KERNEL)
+    {
+      gcc_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
+      gcc_assert (!TARGET_32BIT);
+
+      asm_fprintf (file, "\tmflr %s\n", reg_names[0]);
+      asm_fprintf (file, "\tstd %s,16(%s)\n", reg_names[0], reg_names[1]);
+
+      if (cfun->static_chain_decl != NULL)
+	{
+	  asm_fprintf (file, "\tstd %s,24(%s)\n",
+		       reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
+	  fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
+	  asm_fprintf (file, "\tld %s,24(%s)\n",
+		       reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
+	}
+      else
+	fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
+    }
+
   rs6000_pic_labelno++;
 }
 
@@ -23825,6 +23880,12 @@  rs6000_output_mi_thunk (FILE *file, tree
   SIBLING_CALL_P (insn) = 1;
   emit_barrier ();
 
+  /* Ensure we have a global entry point for the thunk.   ??? We could
+     avoid that if the target routine doesn't need a global entry point,
+     but we do not know whether this is the case at this point.  */
+  if (DEFAULT_ABI == ABI_ELFv2)
+    cfun->machine->r2_setup_needed = true;
+
   /* Run just enough of rest_of_compilation to get the insns emitted.
      There's not really enough bulk here to make other passes such as
      instruction scheduling worth while.  Note that use_thunk calls
@@ -24646,28 +24707,7 @@  output_function_profiler (FILE *file, in
     case ABI_AIX:
     case ABI_ELFv2:
     case ABI_DARWIN:
-      if (!TARGET_PROFILE_KERNEL)
-	{
-	  /* Don't do anything, done in output_profile_hook ().  */
-	}
-      else
-	{
-	  gcc_assert (!TARGET_32BIT);
-
-	  asm_fprintf (file, "\tmflr %s\n", reg_names[0]);
-	  asm_fprintf (file, "\tstd %s,16(%s)\n", reg_names[0], reg_names[1]);
-
-	  if (cfun->static_chain_decl != NULL)
-	    {
-	      asm_fprintf (file, "\tstd %s,24(%s)\n",
-			   reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
-	      fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
-	      asm_fprintf (file, "\tld %s,24(%s)\n",
-			   reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
-	    }
-	  else
-	    fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
-	}
+      /* Don't do anything, done in output_profile_hook ().  */
       break;
     }
 }
@@ -26600,10 +26640,14 @@  rs6000_trampoline_size (void)
       gcc_unreachable ();
 
     case ABI_AIX:
-    case ABI_ELFv2:
       ret = (TARGET_32BIT) ? 12 : 24;
       break;
 
+    case ABI_ELFv2:
+      gcc_assert (!TARGET_32BIT);
+      ret = 32;
+      break;
+
     case ABI_DARWIN:
     case ABI_V4:
       ret = (TARGET_32BIT) ? 40 : 48;
@@ -26632,7 +26676,6 @@  rs6000_trampoline_init (rtx m_tramp, tre
 
     /* Under AIX, just build the 3 word function descriptor */
     case ABI_AIX:
-    case ABI_ELFv2:
       {
 	rtx fnmem, fn_reg, toc_reg;
 
@@ -26660,6 +26703,7 @@  rs6000_trampoline_init (rtx m_tramp, tre
       break;
 
     /* Under V.4/eabi/darwin, __trampoline_setup does the real work.  */
+    case ABI_ELFv2:
     case ABI_DARWIN:
     case ABI_V4:
       emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
@@ -27032,7 +27076,7 @@  rs6000_elf_encode_section_info (tree dec
   if (first
       && TREE_CODE (decl) == FUNCTION_DECL
       && !TARGET_AIX
-      && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2))
+      && DEFAULT_ABI == ABI_AIX)
     {
       rtx sym_ref = XEXP (rtl, 0);
       size_t len = strlen (XSTR (sym_ref, 0));
@@ -27602,7 +27646,7 @@  rs6000_elf_asm_out_destructor (rtx symbo
 void
 rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
 {
-  if (TARGET_64BIT)
+  if (TARGET_64BIT && DEFAULT_ABI != ABI_ELFv2)
     {
       fputs ("\t.section\t\".opd\",\"aw\"\n\t.align 3\n", file);
       ASM_OUTPUT_LABEL (file, name);
@@ -27652,7 +27696,7 @@  rs6000_elf_declare_function_name (FILE *
   ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
   ASM_DECLARE_RESULT (file, DECL_RESULT (decl));
 
-  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+  if (DEFAULT_ABI == ABI_AIX)
     {
       const char *desc_name, *orig_name;
 
@@ -27697,7 +27741,7 @@  rs6000_elf_file_end (void)
     }
 #endif
 #if defined (POWERPC_LINUX) || defined (POWERPC_FREEBSD)
-  if (TARGET_32BIT)
+  if (TARGET_32BIT || DEFAULT_ABI == ABI_ELFv2)
     file_end_indicate_exec_stack ();
 #endif
 }
@@ -30672,7 +30716,7 @@  rs6000_call_aix (rtx value, rtx func_des
 
   /* Handle indirect calls.  */
   if (GET_CODE (func_desc) != SYMBOL_REF
-      || !SYMBOL_REF_FUNCTION_P (func_desc))
+      || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (func_desc)))
     {
       /* Save the TOC into its reserved slot before the call,
 	 and prepare to restore it after the call.  */
@@ -30693,38 +30737,49 @@  rs6000_call_aix (rtx value, rtx func_des
 	  emit_move_insn (stack_toc_mem, toc_reg);
 	}
 
-      /* A function pointer under AIX is a pointer to a data area whose
-	 first word contains the actual address of the function, whose
-	 second word contains a pointer to its TOC, and whose third word
-	 contains a value to place in the static chain register (r11).
-	 Note that if we load the static chain, our "trampoline" need
-	 not have any executable code.  */
-
-      /* Load up address of the actual function.  */
-      func_desc = force_reg (Pmode, func_desc);
-      func_addr = gen_reg_rtx (Pmode);
-      emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc));
-
-      /* Prepare to load the TOC of the called function.  Note that the
-	 TOC load must happen immediately before the actual call so
-	 that unwinding the TOC registers works correctly.  See the
-	 comment in frob_update_context.  */
-      rtx func_toc_offset = GEN_INT (GET_MODE_SIZE (Pmode));
-      rtx func_toc_mem = gen_rtx_MEM (Pmode,
-				      gen_rtx_PLUS (Pmode, func_desc,
-						    func_toc_offset));
-      toc_load = gen_rtx_USE (VOIDmode, func_toc_mem);
-
-      /* If we have a static chain, load it up.  */
-      if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
-	{
-	  rtx sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
-	  rtx func_sc_offset = GEN_INT (2 * GET_MODE_SIZE (Pmode));
-	  rtx func_sc_mem = gen_rtx_MEM (Pmode,
-					 gen_rtx_PLUS (Pmode, func_desc,
-						       func_sc_offset));
-	  emit_move_insn (sc_reg, func_sc_mem);
-	  abi_reg = sc_reg;
+      if (DEFAULT_ABI == ABI_ELFv2)
+	{
+	  /* A function pointer in the ELFv2 ABI is just a plain address, but
+	     the ABI requires it to be loaded into r12 before the call.  */
+	  func_addr = gen_rtx_REG (Pmode, 12);
+	  emit_move_insn (func_addr, func_desc);
+	  abi_reg = func_addr;
+	}
+      else
+	{
+	  /* A function pointer under AIX is a pointer to a data area whose
+	     first word contains the actual address of the function, whose
+	     second word contains a pointer to its TOC, and whose third word
+	     contains a value to place in the static chain register (r11).
+	     Note that if we load the static chain, our "trampoline" need
+	     not have any executable code.  */
+
+	  /* Load up address of the actual function.  */
+	  func_desc = force_reg (Pmode, func_desc);
+	  func_addr = gen_reg_rtx (Pmode);
+	  emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc));
+
+	  /* Prepare to load the TOC of the called function.  Note that the
+	     TOC load must happen immediately before the actual call so
+	     that unwinding the TOC registers works correctly.  See the
+	     comment in frob_update_context.  */
+	  rtx func_toc_offset = GEN_INT (GET_MODE_SIZE (Pmode));
+	  rtx func_toc_mem = gen_rtx_MEM (Pmode,
+					  gen_rtx_PLUS (Pmode, func_desc,
+							func_toc_offset));
+	  toc_load = gen_rtx_USE (VOIDmode, func_toc_mem);
+
+	  /* If we have a static chain, load it up.  */
+	  if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
+	    {
+	      rtx sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
+	      rtx func_sc_offset = GEN_INT (2 * GET_MODE_SIZE (Pmode));
+	      rtx func_sc_mem = gen_rtx_MEM (Pmode,
+					     gen_rtx_PLUS (Pmode, func_desc,
+							   func_sc_offset));
+	      emit_move_insn (sc_reg, func_sc_mem);
+	      abi_reg = sc_reg;
+	    }
 	}
     }
   else
Index: gcc/gcc/config/rs6000/rs6000.md
===================================================================
--- gcc.orig/gcc/config/rs6000/rs6000.md
+++ gcc/gcc/config/rs6000/rs6000.md
@@ -12490,7 +12490,7 @@ 
    (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
    (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
+  "DEFAULT_ABI == ABI_AIX"
   "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3"
   [(set_attr "type" "jmpreg")
    (set_attr "length" "12")])
@@ -12502,11 +12502,36 @@ 
    (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
    (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
+  "DEFAULT_ABI == ABI_AIX"
   "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4"
   [(set_attr "type" "jmpreg")
    (set_attr "length" "12")])
 
+;; Call to indirect functions with the ELFv2 ABI.
+;; Operand0 is the addresss of the function to call
+;; Operand2 is the stack location to hold the current TOC pointer
+
+(define_insn "*call_indirect_elfv2<mode>"
+  [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
+	 (match_operand 1 "" "g,g"))
+   (set (reg:P TOC_REGNUM) (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
+   (clobber (reg:P LR_REGNO))]
+  "DEFAULT_ABI == ABI_ELFv2"
+  "b%T0l\;<ptrload> 2,%2"
+  [(set_attr "type" "jmpreg")
+   (set_attr "length" "8")])
+
+(define_insn "*call_value_indirect_elfv2<mode>"
+  [(set (match_operand 0 "" "")
+	(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
+	      (match_operand 2 "" "g,g")))
+   (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
+   (clobber (reg:P LR_REGNO))]
+  "DEFAULT_ABI == ABI_ELFv2"
+  "b%T1l\;<ptrload> 2,%3"
+  [(set_attr "type" "jmpreg")
+   (set_attr "length" "8")])
+
 
 ;; Call subroutine returning any type.
 (define_expand "untyped_call"
Index: gcc/gcc/config/rs6000/predicates.md
===================================================================
--- gcc.orig/gcc/config/rs6000/predicates.md
+++ gcc/gcc/config/rs6000/predicates.md
@@ -1018,8 +1018,7 @@ 
 (define_predicate "symbol_ref_operand"
   (and (match_code "symbol_ref")
        (match_test "(mode == VOIDmode || GET_MODE (op) == mode)
-		    && ((DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_ELFv2)
-			|| SYMBOL_REF_FUNCTION_P (op))")))
+		    && (DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))")))
 
 ;; Return 1 if op is an operand that can be loaded via the GOT.
 ;; or non-special register register field no cr0
@@ -1049,8 +1048,7 @@ 
 ;; this file.
 (define_predicate "current_file_function_operand"
   (and (match_code "symbol_ref")
-       (match_test "((DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_ELFv2)
-		     || SYMBOL_REF_FUNCTION_P (op))
+       (match_test "(DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))
 		    && ((SYMBOL_REF_LOCAL_P (op)
 			 && ((DEFAULT_ABI != ABI_AIX
 			      && DEFAULT_ABI != ABI_ELFv2)
Index: gcc/gcc/config/rs6000/ppc-asm.h
===================================================================
--- gcc.orig/gcc/config/rs6000/ppc-asm.h
+++ gcc/gcc/config/rs6000/ppc-asm.h
@@ -256,7 +256,30 @@  see the files COPYING3 and COPYING.RUNTI
  * the real function with one or two leading periods respectively.
  */
 
-#if defined (__powerpc64__)
+#if defined(__powerpc64__) && _CALL_ELF == 2
+
+/* Defining "toc" above breaks @toc in assembler code.  */
+#undef toc
+
+#define FUNC_NAME(name) GLUE(__USER_LABEL_PREFIX__,name)
+#define JUMP_TARGET(name) FUNC_NAME(name)
+#define FUNC_START(name) \
+	.type FUNC_NAME(name),@function; \
+	.globl FUNC_NAME(name); \
+FUNC_NAME(name): \
+0:	addis 2,12,(.TOC.-0b)@ha; \
+	addi 2,2,(.TOC.-0b)@l; \
+	.localentry FUNC_NAME(name),.-FUNC_NAME(name)
+
+#define HIDDEN_FUNC(name) \
+  FUNC_START(name) \
+  .hidden FUNC_NAME(name);
+
+#define FUNC_END(name) \
+	.size FUNC_NAME(name),.-FUNC_NAME(name)
+
+#elif defined (__powerpc64__)
+
 #define FUNC_NAME(name) GLUE(.,name)
 #define JUMP_TARGET(name) FUNC_NAME(name)
 #define FUNC_START(name) \
Index: gcc/libitm/config/powerpc/sjlj.S
===================================================================
--- gcc.orig/libitm/config/powerpc/sjlj.S
+++ gcc/libitm/config/powerpc/sjlj.S
@@ -26,7 +26,26 @@ 
 
 #include "asmcfi.h"
 
-#if defined(__powerpc64__) && defined(__ELF__)
+#if defined(__powerpc64__) && _CALL_ELF == 2
+.macro FUNC name
+        .globl  \name
+        .type   \name, @function
+\name:
+0:	addis 2,12,(.TOC.-0b)@ha
+	addi 2,2,(.TOC.-0b)@l
+	.localentry \name, . - \name
+.endm
+.macro END name
+	.size	\name, . - \name
+.endm
+.macro HIDDEN name
+	.hidden	\name
+.endm
+.macro CALL name
+	bl	\name
+	nop
+.endm
+#elif defined(__powerpc64__) && defined(__ELF__)
 .macro FUNC name
         .globl  \name, .\name
         .section ".opd","aw"
@@ -117,6 +136,9 @@  _$0:
 #if defined(_CALL_AIXDESC)
 # define BASE		6*WS
 # define LR_SAVE	2*WS
+#elif _CALL_ELF == 2
+# define BASE		6*WS
+# define LR_SAVE	2*WS
 #elif defined(_CALL_SYSV)
 # define BASE		2*WS
 # define LR_SAVE	1*WS
Index: gcc/libgcc/config/rs6000/tramp.S
===================================================================
--- gcc.orig/libgcc/config/rs6000/tramp.S
+++ gcc/libgcc/config/rs6000/tramp.S
@@ -116,4 +116,70 @@  FUNC_END(__trampoline_setup)
 
 #endif
 
+#elif _CALL_ELF == 2
+	.type	trampoline_initial,@object
+	.align	3
+trampoline_initial:
+	ld	r11,.Lchain(r12)
+	ld	r12,.Lfunc(r12)
+	mtctr	r12
+	bctr
+.Lfunc = .-trampoline_initial
+	.quad	0			/* will be replaced with function address */
+.Lchain = .-trampoline_initial
+	.quad	0			/* will be replaced with static chain */
+
+trampoline_size = .-trampoline_initial
+	.size	trampoline_initial,trampoline_size
+
+
+/* R3 = stack address to store trampoline */
+/* R4 = length of trampoline area */
+/* R5 = function address */
+/* R6 = static chain */
+
+	.pushsection ".toc","aw"
+.LC0:
+	.quad	trampoline_initial-8
+	.popsection
+
+FUNC_START(__trampoline_setup)
+	addis 7,2,.LC0@toc@ha
+	ld 7,.LC0@toc@l(7)	/* trampoline address -8 */
+
+	li	r8,trampoline_size	/* verify that the trampoline is big enough */
+	cmpw	cr1,r8,r4
+	srwi	r4,r4,3		/* # doublewords to move */
+	addi	r9,r3,-8	/* adjust pointer for stdu */
+	mtctr	r4
+	blt	cr1,.Labort
+
+	/* Copy the instructions to the stack */
+.Lmove:
+	ldu	r10,8(r7)
+	stdu	r10,8(r9)
+	bdnz	.Lmove
+
+	/* Store correct function and static chain */
+	std	r5,.Lfunc(r3)
+	std	r6,.Lchain(r3)
+
+	/* Now flush both caches */
+	mtctr	r4
+.Lcache:
+	icbi	0,r3
+	dcbf	0,r3
+	addi	r3,r3,8
+	bdnz	.Lcache
+
+	/* Finally synchronize things & return */
+	sync
+	isync
+	blr
+
+.Labort:
+	bl	JUMP_TARGET(abort)
+	nop
+FUNC_END(__trampoline_setup)
+
 #endif
Index: gcc/libgcc/config/rs6000/linux-unwind.h
===================================================================
--- gcc.orig/libgcc/config/rs6000/linux-unwind.h
+++ gcc/libgcc/config/rs6000/linux-unwind.h
@@ -317,6 +317,8 @@  frob_update_context (struct _Unwind_Cont
 	    = (unsigned int *) _Unwind_GetGR (context, R_LR);
 	  if (insn && *insn == 0xE8410028)
 	    _Unwind_SetGRPtr (context, 2, context->cfa + 40);
+#if _CALL_ELF != 2
+	  /* ELFv2 does not use this function pointer call sequence.  */
 	  else if (pc[0] == 0x4E800421
 		   && pc[1] == 0xE8410028)
 	    {
@@ -327,6 +329,7 @@  frob_update_context (struct _Unwind_Cont
 	      _Unwind_Word sp = _Unwind_GetGR (context, 1);
 	      _Unwind_SetGRPtr (context, 2, (void *)(sp + 40));
 	    }
+#endif
 	}
     }
 #endif
Index: gcc/gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c
+++ gcc/gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c
@@ -33,15 +33,27 @@  reg_parms_t gparms;
 
 
 /* Wrapper to save the GPRs and FPRs and then jump to the real function.  */
+#if _CALL_ELF != 2
+#define FUNC_START(NAME)						\
+	"\t.globl\t" NAME "\n\t"					\
+         ".section \".opd\",\"aw\"\n\t"					\
+         ".align 3\n"							\
+         NAME ":\n\t"							\
+         ".quad .L." NAME ",.TOC.@tocbase,0\n\t"			\
+         ".text\n\t"							\
+         ".type " NAME ", @function\n"					\
+         ".L." NAME ":\n\t"
+#else
+#define FUNC_START(NAME)						\
+	"\t.globl\t" NAME "\n\t"					\
+         ".text\n\t"							\
+         NAME ":\n"							\
+	"0:\taddis 2,12,(.TOC.-0b)@ha\n\t"				\
+	"addi 2,2,(.TOC.-0b)@l\n\t"					\
+	".localentry " NAME ",.-" NAME "\n\t"
+#endif
 #define WRAPPER(NAME)							\
-__asm__ ("\t.globl\t" #NAME "_asm\n\t"					\
-	 ".section \".opd\",\"aw\"\n\t"					\
-	 ".align 3\n"							\
-	 #NAME "_asm:\n\t"						\
-	 ".quad .L." #NAME "_asm,.TOC.@tocbase,0\n\t"			\
-	 ".text\n\t"							\
-	 ".type " #NAME "_asm, @function\n"				\
-	 ".L." #NAME "_asm:\n\t"					\
+__asm__ (FUNC_START (#NAME "_asm")					\
 	 "ld 11,gparms@got(2)\n\t"					\
 	 "std 3,0(11)\n\t"						\
 	 "std 4,8(11)\n\t"						\
Index: gcc/gcc/testsuite/gcc.target/powerpc/no-r11-1.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/powerpc/no-r11-1.c
+++ gcc/gcc/testsuite/gcc.target/powerpc/no-r11-1.c
@@ -1,5 +1,6 @@ 
 /* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
 /* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc_elfv2 } { "*" } { "" } } */
 /* { dg-options "-O2 -mno-pointers-to-nested-functions" } */
 
 int
Index: gcc/gcc/testsuite/gcc.target/powerpc/no-r11-2.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/powerpc/no-r11-2.c
+++ gcc/gcc/testsuite/gcc.target/powerpc/no-r11-2.c
@@ -1,5 +1,6 @@ 
 /* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
 /* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc_elfv2 } { "*" } { "" } } */
 /* { dg-options "-O2 -mpointers-to-nested-functions" } */
 
 int
Index: gcc/gcc/testsuite/gcc.target/powerpc/no-r11-3.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/powerpc/no-r11-3.c
+++ gcc/gcc/testsuite/gcc.target/powerpc/no-r11-3.c
@@ -1,5 +1,6 @@ 
 /* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
 /* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc_elfv2 } { "*" } { "" } } */
 /* { dg-options "-O2 -mno-pointers-to-nested-functions" } */
 
 extern void ext_call (int (func) (void));
Index: gcc/libstdc++-v3/scripts/extract_symvers.in
===================================================================
--- gcc.orig/libstdc++-v3/scripts/extract_symvers.in
+++ gcc/libstdc++-v3/scripts/extract_symvers.in
@@ -53,6 +53,7 @@  SunOS)
   # present on Solaris.
   ${readelf} ${lib} |\
   sed -e 's/ \[<other>: [A-Fa-f0-9]*\] //' -e '/\.dynsym/,/^$/p;d' |\
+  sed -e 's/ \[<localentry>: [0-9]*\] //' |\
   egrep -v ' (LOCAL|UND) ' |\
   egrep -v ' (_DYNAMIC|_GLOBAL_OFFSET_TABLE_|_PROCEDURE_LINKAGE_TABLE_|_edata|_end|_etext)$' |\
   sed -e 's/ <processor specific>: / <processor_specific>:_/g' |\
Index: gcc/libgo/testsuite/gotest
===================================================================
--- gcc.orig/libgo/testsuite/gotest
+++ gcc/libgo/testsuite/gotest
@@ -369,7 +369,7 @@  localname() {
 {
 	text="T"
 	case "$GOARCH" in
-	ppc64) text="D" ;;
+	ppc64) text="[TD]" ;;
 	esac
 
 	symtogo='sed -e s/_test/XXXtest/ -e s/.*_\([^_]*\.\)/\1/ -e s/XXXtest/_test/'