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]

Re: [PATCH] Fix wrong-debug with i?86/x86_64 _GLOBAL_OFFSET_TABLE_ (PR debug/82630)


On Mon, 23 Oct 2017, Jakub Jelinek wrote:

> Hi!
> 
> If all fails, when we can't prove that the PIC register is in some hard
> register, we delegitimize something + foo@GOTOFF as (something -
> _GLOBAL_OFFSET_TABLE_) + foo.  That is reasonable for the middle-end to
> understand what is going on (it will never match in actual instructions
> though), unfortunately when trying to emit that into .debug_info section
> we run into the problem that .long _GLOBAL_OFFSET_TABLE_ etc. is not
> actually assembled as address of _GLOBAL_OFFSET_TABLE_, but as
> _GLOBAL_OFFSET_TABLE_-. (any time the assembler sees _GLOBAL_OFFSET_TABLE_
> symbol by name, it adds the special relocation) and thus we get a bogus
> expression.
> 
> I couldn't come up with a way to express this that wouldn't be even larger
> than what we have, but if we actually not delegitimize it at all and let
> it be emitted as
>   something
>   .byte DW_OP_addr
>   .long foo@GOTOFF
>   .byte DW_OP_plus
> then it works fine and is even shorter than what we used to emit -
>   something
>   .byte DW_OP_addr
>   .long _GLOBAL_OFFSET_TABLE_
>   .byte DW_OP_minus
>   .byte DW_OP_addr
>   .long foo
>   .byte DW_OP_plus
> In order to achieve that, we need to allow selected UNSPECs through
> into debug info, current trunk just gives up on all UNSPECs.
> 
> Fortunately, we already have a hook for rejecting some constants, so
> by adding the rejection of all UNSPECs into the hook and on i386 overriding
> that hook we achieve what we want.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2017-10-23  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR debug/82630
> 	* target.def (const_not_ok_for_debug_p): Default to
> 	default_const_not_ok_for_debug_p instead of hook_bool_rtx_false.
> 	* targhooks.h (default_const_not_ok_for_debug_p): New declaration.
> 	* targhooks.c (default_const_not_ok_for_debug_p): New function.
> 	* dwarf2out.c (const_ok_for_output_1): Only reject UNSPECs for
> 	which targetm.const_not_ok_for_debug_p returned true.
> 	* config/arm/arm.c (arm_const_not_ok_for_debug_p): Return true
> 	for UNSPECs.
> 	* config/powerpcspe/powerpcspe.c (rs6000_const_not_ok_for_debug_p):
> 	Likewise.
> 	* config/rs6000/rs6000.c (rs6000_const_not_ok_for_debug_p): Likewise.
> 	* config/i386/i386.c (ix86_delegitimize_address_1): Don't delegitimize
> 	UNSPEC_GOTOFF with addend into addend - _GLOBAL_OFFSET_TABLE_ + symbol
> 	if !base_term_p.
> 	(ix86_const_not_ok_for_debug_p): New function.
> 	(i386_asm_output_addr_const_extra): Handle UNSPEC_GOTOFF.
> 	(TARGET_CONST_NOT_OK_FOR_DEBUG_P): Redefine.
> 
> 	* g++.dg/guality/pr82630.C: New test.
> 
> --- gcc/target.def.jj	2017-10-10 11:54:13.000000000 +0200
> +++ gcc/target.def	2017-10-20 14:07:06.463135128 +0200
> @@ -2822,7 +2822,7 @@ DEFHOOK
>   "This hook should return true if @var{x} should not be emitted into\n\
>  debug sections.",
>   bool, (rtx x),
> - hook_bool_rtx_false)
> + default_const_not_ok_for_debug_p)
>  
>  /* Given an address RTX, say whether it is valid.  */
>  DEFHOOK
> --- gcc/targhooks.c.jj	2017-10-13 19:02:08.000000000 +0200
> +++ gcc/targhooks.c	2017-10-20 14:26:07.945464025 +0200
> @@ -177,6 +177,14 @@ default_legitimize_address_displacement
>    return false;
>  }
>  
> +bool
> +default_const_not_ok_for_debug_p (rtx x)
> +{
> +  if (GET_CODE (x) == UNSPEC)

What about UNSPEC_VOLATILE?

> +    return true;
> +  return false;
> +}
> +
>  rtx
>  default_expand_builtin_saveregs (void)
>  {
> --- gcc/targhooks.h.jj	2017-10-13 19:02:08.000000000 +0200
> +++ gcc/targhooks.h	2017-10-20 14:26:07.945464025 +0200
> @@ -26,6 +26,7 @@ extern void default_external_libcall (rt
>  extern rtx default_legitimize_address (rtx, rtx, machine_mode);
>  extern bool default_legitimize_address_displacement (rtx *, rtx *,
>  						     machine_mode);
> +extern bool default_const_not_ok_for_debug_p (rtx);
>  
>  extern int default_unspec_may_trap_p (const_rtx, unsigned);
>  extern machine_mode default_promote_function_mode (const_tree, machine_mode,
> --- gcc/dwarf2out.c.jj	2017-10-19 16:18:44.000000000 +0200
> +++ gcc/dwarf2out.c	2017-10-20 14:39:49.432647598 +0200
> @@ -13740,9 +13740,17 @@ expansion_failed (tree expr, rtx rtl, ch
>  static bool
>  const_ok_for_output_1 (rtx rtl)
>  {
> -  if (GET_CODE (rtl) == UNSPEC)
> +  if (targetm.const_not_ok_for_debug_p (rtl))
>      {
> -      /* If delegitimize_address couldn't do anything with the UNSPEC, assume
> +      if (GET_CODE (rtl) != UNSPEC)
> +	{
> +	  expansion_failed (NULL_TREE, rtl,
> +			    "Expression rejected for debug by the backend.\n");
> +	  return false;
> +	}
> +
> +      /* If delegitimize_address couldn't do anything with the UNSPEC, and
> +	 the target hook doesn't explicitly allow it in debug info, assume
>  	 we can't express it in the debug info.  */
>        /* Don't complain about TLS UNSPECs, those are just too hard to
>  	 delegitimize.  Note this could be a non-decl SYMBOL_REF such as
> @@ -13769,13 +13777,6 @@ const_ok_for_output_1 (rtx rtl)
>        return false;
>      }
>  
> -  if (targetm.const_not_ok_for_debug_p (rtl))
> -    {
> -      expansion_failed (NULL_TREE, rtl,
> -			"Expression rejected for debug by the backend.\n");
> -      return false;
> -    }
> -
>    /* FIXME: Refer to PR60655. It is possible for simplification
>       of rtl expressions in var tracking to produce such expressions.
>       We should really identify / validate expressions
> --- gcc/config/arm/arm.c.jj	2017-10-19 16:18:44.000000000 +0200
> +++ gcc/config/arm/arm.c	2017-10-20 14:28:06.302046887 +0200
> @@ -30391,6 +30391,8 @@ arm_const_not_ok_for_debug_p (rtx p)
>    tree decl_op0 = NULL;
>    tree decl_op1 = NULL;
>  
> +  if (GET_CODE (p) == UNSPEC)
> +    return true;
>    if (GET_CODE (p) == MINUS)
>      {
>        if (GET_CODE (XEXP (p, 1)) == SYMBOL_REF)
> --- gcc/config/powerpcspe/powerpcspe.c.jj	2017-10-17 22:10:10.000000000 +0200
> +++ gcc/config/powerpcspe/powerpcspe.c	2017-10-20 14:28:40.823633544 +0200
> @@ -9536,6 +9536,8 @@ rs6000_delegitimize_address (rtx orig_x)
>  static bool
>  rs6000_const_not_ok_for_debug_p (rtx x)
>  {
> +  if (GET_CODE (x) == UNSPEC)
> +    return true;
>    if (GET_CODE (x) == SYMBOL_REF
>        && CONSTANT_POOL_ADDRESS_P (x))
>      {
> --- gcc/config/rs6000/rs6000.c.jj	2017-10-17 22:10:10.000000000 +0200
> +++ gcc/config/rs6000/rs6000.c	2017-10-20 14:29:01.066391168 +0200
> @@ -8985,6 +8985,8 @@ rs6000_delegitimize_address (rtx orig_x)
>  static bool
>  rs6000_const_not_ok_for_debug_p (rtx x)
>  {
> +  if (GET_CODE (x) == UNSPEC)
> +    return true;
>    if (GET_CODE (x) == SYMBOL_REF
>        && CONSTANT_POOL_ADDRESS_P (x))
>      {
> --- gcc/config/i386/i386.c.jj	2017-10-20 09:16:10.000000000 +0200
> +++ gcc/config/i386/i386.c	2017-10-20 14:53:19.520953612 +0200
> @@ -16657,13 +16657,17 @@ ix86_delegitimize_address_1 (rtx x, bool
>  	 movl foo@GOTOFF(%ecx), %edx
>  	 in which case we return (%ecx - %ebx) + foo
>  	 or (%ecx - _GLOBAL_OFFSET_TABLE_) + foo if pseudo_pic_reg
> -	 and reload has completed.  */
> +	 and reload has completed.  Don't do the latter for debug,
> +	 as _GLOBAL_OFFSET_TABLE_ can't be expressed in the assembly.  */
>        if (pic_offset_table_rtx
>  	  && (!reload_completed || !ix86_use_pseudo_pic_reg ()))
>          result = gen_rtx_PLUS (Pmode, gen_rtx_MINUS (Pmode, copy_rtx (addend),
>  						     pic_offset_table_rtx),
>  			       result);
> -      else if (pic_offset_table_rtx && !TARGET_MACHO && !TARGET_VXWORKS_RTP)
> +      else if (base_term_p
> +	       && pic_offset_table_rtx
> +	       && !TARGET_MACHO
> +	       && !TARGET_VXWORKS_RTP)
>  	{
>  	  rtx tmp = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME);
>  	  tmp = gen_rtx_MINUS (Pmode, copy_rtx (addend), tmp);
> @@ -16716,6 +16720,25 @@ ix86_find_base_term (rtx x)
>  
>    return ix86_delegitimize_address_1 (x, true);
>  }
> +
> +/* Return true if X shouldn't be emitted into the debug info.
> +   Disallow UNSPECs other than @gotoff - we can't emit _GLOBAL_OFFSET_TABLE_
> +   symbol easily into the .debug_info section, so we need not to
> +   delegitimize, but instead assemble as @gotoff.
> +   Disallow _GLOBAL_OFFSET_TABLE_ SYMBOL_REF - the assembler magically
> +   assembles that as _GLOBAL_OFFSET_TABLE_-. expression.  */
> +
> +static bool
> +ix86_const_not_ok_for_debug_p (rtx x)
> +{
> +  if (GET_CODE (x) == UNSPEC && XINT (x, 1) != UNSPEC_GOTOFF)
> +    return true;
> +
> +  if (SYMBOL_REF_P (x) && strcmp (XSTR (x, 0), GOT_SYMBOL_NAME) == 0)
> +    return true;
> +
> +  return false;
> +}
>  
>  static void
>  put_condition_code (enum rtx_code code, machine_mode mode, bool reverse,
> @@ -18032,6 +18055,10 @@ i386_asm_output_addr_const_extra (FILE *
>    op = XVECEXP (x, 0, 0);
>    switch (XINT (x, 1))
>      {
> +    case UNSPEC_GOTOFF:
> +      output_addr_const (file, op);
> +      fputs ("@gotoff", file);
> +      break;
>      case UNSPEC_GOTTPOFF:
>        output_addr_const (file, op);
>        /* FIXME: This might be @TPOFF in Sun ld.  */
> @@ -49415,6 +49442,9 @@ ix86_run_selftests (void)
>  #undef TARGET_DELEGITIMIZE_ADDRESS
>  #define TARGET_DELEGITIMIZE_ADDRESS ix86_delegitimize_address
>  
> +#undef TARGET_CONST_NOT_OK_FOR_DEBUG_P
> +#define TARGET_CONST_NOT_OK_FOR_DEBUG_P ix86_const_not_ok_for_debug_p
> +
>  #undef TARGET_MS_BITFIELD_LAYOUT_P
>  #define TARGET_MS_BITFIELD_LAYOUT_P ix86_ms_bitfield_layout_p
>  
> --- gcc/testsuite/g++.dg/guality/pr82630.C.jj	2017-10-20 15:23:37.978128740 +0200
> +++ gcc/testsuite/g++.dg/guality/pr82630.C	2017-10-20 15:30:39.608050350 +0200
> @@ -0,0 +1,58 @@
> +// PR debug/82630
> +// { dg-do run }
> +// { dg-additional-options "-fPIC" { target fpic } }
> +
> +struct C
> +{
> +  int &c;
> +  long d;
> +  __attribute__((always_inline)) C (int &x) : c(x), d() {}
> +};
> +int v;
> +
> +__attribute__((noipa)) void
> +fn1 (const void *x)
> +{
> +  asm volatile ("" : : "g" (x) : "memory");
> +}
> +
> +__attribute__((noipa)) void
> +fn2 (C x)
> +{
> +  int a = x.c + x.d;
> +  asm volatile ("" : : "g" (a) : "memory");
> +}
> +
> +__attribute__((noipa)) void
> +fn3 (void)
> +{
> +  asm volatile ("" : : : "memory");
> +}
> +
> +__attribute__((noipa))
> +#ifdef __i386__
> +__attribute__((regparm (2)))
> +#endif
> +static void
> +fn4 (int *x, const char *y, C z)
> +{
> +  fn2 (C (*x));
> +  fn1 ("baz");
> +  fn2 (z);	// { dg-final { gdb-test 41 "y\[0\]" "'f'" } }
> +  fn1 ("baz");	// { dg-final { gdb-test 41 "y\[1\]" "'o'" } }
> +}
> +
> +__attribute__((noipa)) void
> +fn5 (int *x)
> +{
> +  fn4 (x, "foo", C (*x));
> +  fn3 ();
> +}
> +
> +int
> +main ()
> +{
> +  int a = 10;
> +  fn5 (&a);
> +  return 0;
> +}
> 
> 	Jakub
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)


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