This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RS6000] Fix -mlongcall with nested functions on AIX


Hi,

-mlongcall miscompiles nested functions with the AIX ABI.  The problem is 
that, when -mlongcall is in effect, rs6000_call_aix redirects all calls to:

  /* Handle indirect calls.  */
  if (GET_CODE (func_desc) != SYMBOL_REF
      || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (func_desc)))

and then

	  /* 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.  */

But, if the call was originally direct, no "trampoline" has been built, which 
means that the value loaded into the static chain register is garbage.  That's 
sort of OK, except when the called function is nested because the static chain 
register has already been loaded with the proper static chain value by the 
generic code, so overwriting it with garbage breaks the program.

Tested on PowerPC/AIX, OK for the mainline?


2014-10-17  Eric Botcazou  <ebotcazou@adacore.com>

	* config/rs6000/rs6000.c (rs6000_call_aix): For the AIX ABI, do not
	load the static chain if the call was originally direct.


2014-10-17  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc.target/powerpc/longcall-2.c: New test.


-- 
Eric Botcazou
Index: config/rs6000/rs6000.c
===================================================================
--- config/rs6000/rs6000.c	(revision 216252)
+++ config/rs6000/rs6000.c	(working copy)
@@ -32568,6 +32568,8 @@ rs6000_legitimate_constant_p (enum machi
 void
 rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
 {
+  const bool direct_call_p
+    = GET_CODE (func_desc) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (func_desc);
   rtx toc_reg = gen_rtx_REG (Pmode, TOC_REGNUM);
   rtx toc_load = NULL_RTX;
   rtx toc_restore = NULL_RTX;
@@ -32636,8 +32638,11 @@ rs6000_call_aix (rtx value, rtx func_des
 							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)
+	  /* If we have a static chain, load it up.  But, if the call was
+	     originally direct, the 3rd word has not been written since no
+	     trampoline has been built, so we ought not to load it, lest we
+	     override a static chain value.  */
+	  if (!direct_call_p && 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));
/* { dg-do run } */
/* { dg-options "-mlongcall" } */

extern void abort (void);

#define VAL 12345678

int j = VAL;

void
bar (void)
{
  if (j != VAL)
    abort ();
}

int
main (void)
{
  int i = VAL;

  int foo (void)
  {
    if (i != VAL)
      abort ();
  }

  foo ();
  bar ();

  return 0;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]