diff mbox

[PR,debug/60655] Power/GCC: Reject cross-section symbol subtraction

Message ID alpine.DEB.1.10.1409020249380.2958@tp.orcam.me.uk
State New
Headers show

Commit Message

Maciej W. Rozycki Sept. 2, 2014, 10:28 a.m. UTC
Hi,

 Similarly to ARM, where this issue was seen originally, and likely many 
other targets, the Power ABI does not appear to have a relocation defined 
to support taking a difference of two symbols in different sections each. 
This is seen as a failure in gcc.c-torture/compile/pr60655-2.c:

Executing on host: powerpc-linux-gnu-gcc  -fno-diagnostics-show-caret -fdiagnostics-color=never   -O3 -g  -w -c  -o pr60655-2.o .../gcc/testsuite/gcc.c-torture/compile/pr60655-2.c    (timeout = 300)
/tmp/ccAfNLMj.s: Assembler messages:
/tmp/ccAfNLMj.s:932: Error: can't resolve `L0^A' {*ABS* section} - `.LANCHOR0' {.bss section}
/tmp/ccAfNLMj.s:932: Error: expression too complex
compiler exited with status 1
output is:
/tmp/ccAfNLMj.s: Assembler messages:
/tmp/ccAfNLMj.s:932: Error: can't resolve `L0^A' {*ABS* section} - `.LANCHOR0' {.bss section}
/tmp/ccAfNLMj.s:932: Error: expression too complex

FAIL: gcc.c-torture/compile/pr60655-2.c  -O3 -g  (test for excess errors)
Excess errors:
/tmp/ccAfNLMj.s:932: Error: can't resolve `L0^A' {*ABS* section} - `.LANCHOR0' {.bss section}
/tmp/ccAfNLMj.s:932: Error: expression too complex

Here's a port of the original ARM fix (commit 209269), that removes the 
failure for me.

 Regression-tested with the following powerpc-gnu-linux multilibs:

-mcpu=603e
-mcpu=603e -msoft-float
-mcpu=8540 -mfloat-gprs=single -mspe=yes -mabi=spe
-mcpu=8548 -mfloat-gprs=double -mspe=yes -mabi=spe
-mcpu=7400 -maltivec -mabi=altivec
-mcpu=e6500 -maltivec -mabi=altivec
-mcpu=e5500 -m64
-mcpu=e6500 -m64 -maltivec -mabi=altivec

 OK for trunk and 4.9?

2014-09-02  Maciej W. Rozycki  <macro@codesourcery.com>

	PR debug/60655
	* config/rs6000/rs6000.c (rs6000_const_not_ok_for_debug_p):
	Reject MINUS with SYM_REFs in different sections.

  Maciej

gcc-rs6000-minus-not-ok-for-debug.diff

Comments

Alan Modra Sept. 3, 2014, 5:31 a.m. UTC | #1
On Tue, Sep 02, 2014 at 09:47:15AM -0400, David Edelsohn wrote:
> Alan,
> 
> Any feedback?

It is just papering over the real bug(s), of course, so I'd be
inclined to say this doesn't belong on trunk.

If you take a look at the assembly that is failing, you find gcc is
trying to output a location expression for a parameter of mp_compare.
After replacing the 335-.LANCHOR0 with 0:

objdump -sj.debug_loc
 0180                   000000f8 00000104
 0190 000f7a00 03000000 00220300 00000022
 01a0 9f

readelf -r
00000195  00000401 R_PPC_ADDR32           00000000   .bss + 0

readelf -wo
    00000188 000000f8 00000104 (DW_OP_breg10 (r10): 0; DW_OP_addr: 0; DW_OP_plus; DW_OP_addr: 0; DW_OP_plus; DW_OP_stack_value)

Putting this all together, and knowing that .LANCHOR0 == .bss+0, the
expresssion is really:

    00000188 000000f8 00000104 (DW_OP_breg10 (r10): 0; DW_OP_addr: .LANCHOR0; DW_OP_plus; DW_OP_addr: 335-.LANCHOR0; DW_OP_plus; DW_OP_stack_value)

ie. ((r10) + 0) + (.LANCHOR0) + (335-.LANCHOR0)

Clearly this could be simplified to (r10) + 335, so it might be that
var-tracking is being confused by section anchors.  However, it is
more than just a missing simplification because the location
expression doesn't make any sense at all..


In fact if you look at the corresponding location expression for
-fno-section-anchors code you get something quite screwy too.

0000018f 00000108 00000114 (DW_OP_breg10 (r10): 0; DW_OP_addr: 144; DW_OP_plus; DW_OP_stack_value

which is (r10) + &modulus.

If I have the interpretation of all the debug info correct, what this
is saying is that in the epilogue of upton_modmult, the value for the
"r2" parameter of mp_compare is found by adding the address of
"modulus" to the contents of r10.  The correct answer is simply that
the "r2" parameter of mp_compare is in r10.


> On Tue, Sep 2, 2014 at 6:28 AM, Maciej W. Rozycki
> <macro@codesourcery.com> wrote:
> > Hi,
> >
> >  Similarly to ARM, where this issue was seen originally, and likely many
> > other targets, the Power ABI does not appear to have a relocation defined
> > to support taking a difference of two symbols in different sections each.
> > This is seen as a failure in gcc.c-torture/compile/pr60655-2.c:
diff mbox

Patch

Index: gcc-fsf-trunk-quilt/gcc/config/rs6000/rs6000.c
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/rs6000/rs6000.c	2014-08-26 20:30:10.348973028 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/rs6000/rs6000.c	2014-09-01 17:09:23.748927487 +0100
@@ -6974,7 +6974,13 @@  rs6000_delegitimize_address (rtx orig_x)
 
 /* Return true if X shouldn't be emitted into the debug info.
    The linker doesn't like .toc section references from
-   .debug_* sections, so reject .toc section symbols.  */
+   .debug_* sections, so reject .toc section symbols.
+
+   Also as a temporary fix for PR60655 we reject certain MINUS
+   expressions.  Ideally we need to handle most of these cases in
+   the generic part but currently we reject minus (..) (sym_ref).
+   We try to ameliorate the case with minus (sym_ref1) (sym_ref2)
+   where they are in the same section.  */
 
 static bool
 rs6000_const_not_ok_for_debug_p (rtx x)
@@ -6988,6 +6994,35 @@  rs6000_const_not_ok_for_debug_p (rtx x)
 	return true;
     }
 
+  if (GET_CODE (x) == MINUS)
+    {
+      tree decl_op0 = NULL;
+      tree decl_op1 = NULL;
+
+      if (GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
+       {
+	 decl_op1 = SYMBOL_REF_DECL (XEXP (x, 1));
+	 if (decl_op1
+	     && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+	     && (decl_op0 = SYMBOL_REF_DECL (XEXP (x, 0))))
+	   {
+	     if ((TREE_CODE (decl_op1) == VAR_DECL
+		  || TREE_CODE (decl_op1) == CONST_DECL)
+		 && (TREE_CODE (decl_op0) == VAR_DECL
+		     || TREE_CODE (decl_op0) == CONST_DECL))
+	       return (get_variable_section (decl_op1, false)
+		       != get_variable_section (decl_op0, false));
+
+	     if (TREE_CODE (decl_op1) == LABEL_DECL
+		 && TREE_CODE (decl_op0) == LABEL_DECL)
+	       return (DECL_CONTEXT (decl_op1)
+		       != DECL_CONTEXT (decl_op0));
+	   }
+
+	 return true;
+       }
+    }
+
   return false;
 }