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]

[committed] Fix PIC regression with pointer-to-member functions on s390x


Hello,

this fixes a bug where GCC would generate a call to a non-local function
without going via the PLT although -fPIC was given.  The problem was that
the call insn would accept any (call (symbol_ref)) pattern, even if the
symbol_ref in question was non-local and flag_pic was true.

This doesn't usually show up as a problem, since the call expander always
replaces the symbol_ref by an unspec construction used to represent the
PLT call.  However, in a particular case involving C++ pointer-to-member
functions, the problem would show up.  The test case below is a reduction
of a real-world application involving the STL library.

With pointer-to-member function pointers, the front-end would generate
code that loads the value of the pointer into an integral variable and
test the low bit.  To do so in the -fPIC case, the back-end generates
a load from a GOT slot.  That load instruction gets marked with an
REG_EQUAL note carrying the original SYMBOL_REF.

Now, later on the code actually *calls* the function via the pointer
read from the GOT.  Due to some optimizations in the mean time, combine
is able to notice that the instruction loading that pointer value carries
a REG_EQUAL note, and attempts to insert that value into the call
instruction.  Due to the bug in the predicate, this succecces, and the
indirect call instruction is transformed into a direct call to the
original SYMBOL_REF, without going via the PLT.

The patch below fixes the problem by making the predicate refuse non-
local function symbols if flag_pic is true.

Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux on
mainline, 4.2 branch, and 4.1 branch.  Committed to all three branches.

Bye,
Ulrich


ChangeLog:

	* config/s390/predicates.md ("bras_sym_operand"): Do not accept
	nonlocal function symbols if flag_pic.

testsuite/ChangeLog:

	* g++.dg/other/s390-1.C: New testcase.


Index: gcc/testsuite/g++.dg/other/s390-1.C
===================================================================
*** gcc/testsuite/g++.dg/other/s390-1.C	(revision 0)
--- gcc/testsuite/g++.dg/other/s390-1.C	(revision 0)
***************
*** 0 ****
--- 1,32 ----
+ // { dg-do compile { target s390x-*-* } }
+ // { dg-options "-O3 -fPIC" }
+ 
+ class A
+ {
+ public:
+   void f (void) { _M_a = 0; }
+   void g (void) { _M_a = 1; }
+   void h (void);
+ 
+ private:
+   int _M_a;
+ };
+ 
+ class B : virtual public A
+ {
+ };
+ 
+ void
+ test (B& x)
+ {
+   for (int i = 0; i < 17; i++)
+    {
+      x.f ();
+      (x.*&A::g) ();
+      x.h ();
+    }
+ }
+ 
+ // Check that every call to A::g goes via the PLT.
+ // { dg-final { scan-assembler-not "brasl\[^@\]*\n" } }
+ 
Index: gcc/config/s390/predicates.md
===================================================================
*** gcc/config/s390/predicates.md	(revision 117571)
--- gcc/config/s390/predicates.md	(working copy)
***************
*** 62,68 ****
  ;; Allow SYMBOL_REFs and @PLT stubs.
  
  (define_special_predicate "bras_sym_operand"
!   (ior (match_code "symbol_ref")
         (and (match_code "const")
  	    (and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC")
  		 (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_PLT")))))
--- 62,69 ----
  ;; Allow SYMBOL_REFs and @PLT stubs.
  
  (define_special_predicate "bras_sym_operand"
!   (ior (and (match_code "symbol_ref")
! 	    (match_test "!flag_pic || SYMBOL_REF_LOCAL_P (op)"))
         (and (match_code "const")
  	    (and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC")
  		 (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_PLT")))))
-- 
  Dr. Ulrich Weigand
  Linux on zSeries Development
  Ulrich.Weigand@de.ibm.com


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