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]

[PATCH] Fix -fpic/-fPIC virtual thunks on s390 -m31


Hi!

s390 31-bit .plt slots require %r12 to be loaded with .plt's shared library
_GLOBAL_OFFSET_TABLE_. As we cannot load that (%r12 is call-saved and we
don't return back into the thunk (we would have to copy arguments otherwise
and we don't know how many there are), we cannot use .plt.
The following patch changes 31-bit thunks calling to non-local functions
in -fpic/-fPIC to load the function pointer from .got instead.
For -fpic it uses:
basr %r1,0
.L4:
a %r1,.L5-.L4(%r1)
l %r1,the_function@GOT12(%r1)
br %r1
.align 4
.L5:
.long _GLOBAL_OFFSET_TABLE_-.L4
and for -fPIC:
basr %r1,0
.L6:
l %r0,.L7-4-.L6(%r1)
a %r1,.L7-.L6(%r1)
ar %r1,%r0
l %r1,0(%r1)
br %r1
.align 4
.long the_function@GOT
.L7:
.long _GLOBAL_OFFSET_TABLE_-.L6
Ok to commit (or are different sequences better)?
3.3 has the same bug.

2003-06-20  Jakub Jelinek  <jakub@redhat.com>

	* config/s390/s390.c (s390_output_mi_thunk): Avoid .plt in -m31
	mode, as it requires pic register loaded.

--- gcc/config/s390/s390.c.jj	2003-05-17 04:59:02.000000000 -0400
+++ gcc/config/s390/s390.c	2003-06-20 12:05:21.000000000 -0400
@@ -6483,13 +6483,16 @@ s390_output_mi_thunk (file, thunk, delta
      HOST_WIDE_INT vcall_offset;
      tree function;
 {
-  rtx op[9];
+  rtx op[10];
+  int nonlocal = 0;
 
   /* Operand 0 is the target function.  */
   op[0] = XEXP (DECL_RTL (function), 0);
   if (flag_pic && !SYMBOL_REF_LOCAL_P (op[0]))
     {
-      op[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[0]), 113);
+      nonlocal = 1;
+      op[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[0]),
+			      TARGET_64BIT ? 113 : flag_pic == 2 ? 112 : 110);
       op[0] = gen_rtx_CONST (Pmode, op[0]);
     }
 
@@ -6514,6 +6517,9 @@ s390_output_mi_thunk (file, thunk, delta
   op[7] = NULL_RTX;
   op[8] = NULL_RTX;
 
+  /* Operand 9 can be used for temporary register.  */
+  op[9] = NULL_RTX;
+
   /* Generate code.  */
   if (TARGET_64BIT)
     {
@@ -6644,14 +6650,39 @@ s390_output_mi_thunk (file, thunk, delta
 
       /* Jump to target.  */
       op[8] = gen_label_rtx ();
+
       if (!flag_pic)
 	output_asm_insn ("l\t%4,%8-%5(%4)", op);
-      else
+      else if (!nonlocal)
 	output_asm_insn ("a\t%4,%8-%5(%4)", op);
+      /* We cannot call through .plt, since .plt requires %r12 loaded.  */
+      else if (flag_pic == 1)
+	{
+	  output_asm_insn ("a\t%4,%8-%5(%4)", op);
+	  output_asm_insn ("l\t%4,%0(%4)", op);
+	}
+      else if (flag_pic == 2)
+	{
+	  op[9] = gen_rtx_REG (Pmode, 0);
+	  output_asm_insn ("l\t%9,%8-4-%5(%4)", op);
+	  output_asm_insn ("a\t%4,%8-%5(%4)", op);
+	  output_asm_insn ("ar\t%4,%9", op);
+	  output_asm_insn ("l\t%4,0(%4)", op);
+	}
+
       output_asm_insn ("br\t%4", op);
 
       /* Output literal pool.  */
       output_asm_insn (".align\t4", op);
+
+      if (nonlocal && flag_pic == 2)
+	output_asm_insn (".long\t%0", op);
+      if (nonlocal)
+	{
+	  op[0] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+	  SYMBOL_REF_FLAGS (op[0]) = SYMBOL_FLAG_LOCAL;
+	}
+
       (*targetm.asm_out.internal_label) (file, "L", CODE_LABEL_NUMBER (op[8]));
       if (!flag_pic)
 	output_asm_insn (".long\t%0", op);

	Jakub


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