Bug 61976 - aix64: Data corruption in struct passed by value
Summary: aix64: Data corruption in struct passed by value
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.7.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-07-31 12:27 UTC by mr1978
Modified: 2019-05-15 17:12 UTC (History)
3 users (show)

See Also:
Host:
Target: powerpc-ibm-aix*
Build:
Known to work:
Known to fail: 4.8.1, 4.8.4, 4.9.0, 4.9.2
Last reconfirmed: 2014-07-31 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description mr1978 2014-07-31 12:27:39 UTC
Test program:
   #include <stdio.h>

   struct Demo { float a; };
 
   void foo( const Demo byval, const Demo &byref )
   {
      printf( "byval: %f\n", (double) byval.a );
      printf( "byref: %f\n", (double) byref.a );
   }

   int main()
   {
      Demo a = { 1.23 };
      foo( a, a );
      return 0;
   }

When I compile and run this under AIX, the first argument is corrupted:

    g++ -maix64 -o demo demo.c
    ./demo
    byval: -0.000000
    byref: 1.230000

The problem does not occur with -maix32

GCC version:
Target: powerpc-ibm-aix6.1.0.0
Configured with: /common/mringe/gcc47_alt/gcc-4.7.2/configure --prefix=/common/mringe/gcc47_alt/local --with-as=/usr/bin/as --with-ld=/usr/bin/ld --enable-languages=c,c++ --enable-threads --disable-nls --disable-shared --with-gmp=/common/mringe/gcc47_alt/local --with-mpfr=/common/mringe/gcc47_alt/local --with-mpc=/common/mringe/gcc47_alt/local
Thread model: aix
gcc version 4.7.2 (GCC)
Comment 1 Jonathan Wakely 2014-07-31 13:13:15 UTC
GCC 4.7 is no longer supported, but I can conform the bug with GCC 4.8.1 on powerpc-ibm-aix7.1.0.0
Comment 2 David Edelsohn 2015-02-10 19:26:23 UTC
This is caused by the GCC aggregate (struct) padding implementation for AIX.
Comment 3 David Edelsohn 2018-11-27 18:03:54 UTC
GCC is passing aggregates containing a single member in the mode of the member instead of following the ABI for aggregates.

USE_FP_FOR_ARG_P tests the MODE of the argument, which GCC presents as the underlying MODE, e.g., the mode of the "byval" argument is SFmode, not SImode.

This ABI bug also is present for the PPC64 ELFv1 ABI, but is silently hidden because PPC64 ELFv1 pads arguments downward like a numerical value while AIX pads arguments upwards like a string.

The following patch seems to fix the oversight. I suspect that this only should be fixed for AIX and not for Linux.

Index: rs6000.c
===================================================================
--- rs6000.c    (revision 265577)
+++ rs6000.c    (working copy)
@@ -11915,7 +11915,8 @@
       if (elt_mode == TDmode && (cum->fregno % 2) == 1)
        cum->fregno++;
 
-      if (USE_FP_FOR_ARG_P (cum, elt_mode))
+      if (USE_FP_FOR_ARG_P (cum, elt_mode)
+         && (TREE_CODE (type) != RECORD_TYPE || DEFAULT_ABI != ABI_AIX))
        {
          rtx rvec[GP_ARG_NUM_REG + AGGR_ARG_NUM_REG + 1];
          rtx r, off;
Comment 4 David Edelsohn 2018-12-04 15:52:23 UTC
Author: dje
Date: Tue Dec  4 15:51:51 2018
New Revision: 266786

URL: https://gcc.gnu.org/viewcvs?rev=266786&root=gcc&view=rev
Log:
        PR target/61976
        * config/rs6000/rs6000.c (rs6000_function_arg): Don't pass aggregates
        in FPRs on AIX.
        (rs6000_arg_partial_bytes): Same.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/rs6000/rs6000.c
Comment 5 David Edelsohn 2019-05-15 17:02:13 UTC
Author: dje
Date: Wed May 15 17:01:42 2019
New Revision: 271255

URL: https://gcc.gnu.org/viewcvs?rev=271255&root=gcc&view=rev
Log:
        * xcoffout.h (xcoff_private_rodata_section_name): Declare.
        * xcoffout.c (xcoff_private_rodata_section_name): Define.
        * config/rs6000/rs6000.c (rs6000_xcoff_asm_init_sections): Create
        read_only_private_data_section using coff_private_rodata_section_name.
        (rs6000_xcoff_file_start): Generate coff_private_rodata_section_name.

        PR target/61976
        * config/rs6000/rs6000.c (rs6000_function_arg): Don't pass aggregates
        in FPRs on AIX. Ensure type is non-NULL.
        (rs6000_arg_partial_bytes): Same.

Modified:
    branches/gcc-8-branch/gcc/ChangeLog
    branches/gcc-8-branch/gcc/config/rs6000/rs6000.c
    branches/gcc-8-branch/gcc/xcoffout.c
    branches/gcc-8-branch/gcc/xcoffout.h
Comment 6 David Edelsohn 2019-05-15 17:12:02 UTC
Author: dje
Date: Wed May 15 17:11:31 2019
New Revision: 271257

URL: https://gcc.gnu.org/viewcvs?rev=271257&root=gcc&view=rev
Log:
        Backport from mainline
        2019-04-11  David Edelsohn  <dje.gcc@gmail.com>
        * xcoffout.h (xcoff_private_rodata_section_name): Declare.
        * xcoffout.c (xcoff_private_rodata_section_name): Define.
        * config/rs6000/rs6000.c (rs6000_xcoff_asm_init_sections): Create
        read_only_private_data_section using coff_private_rodata_section_name.
        (rs6000_xcoff_file_start): Generate coff_private_rodata_section_name.

        2018-12-04  David Edelsohn  <dje.gcc@gmail.com>
        2018-12-13  David Edelsohn  <dje.gcc@gmail.com>
        PR target/61976
        * config/rs6000/rs6000.c (rs6000_function_arg): Don't pass aggregates
        in FPRs on AIX. Ensure type is non-NULL.
        (rs6000_arg_partial_bytes): Same.

Modified:
    branches/gcc-7-branch/gcc/ChangeLog
    branches/gcc-7-branch/gcc/config/rs6000/rs6000.c
    branches/gcc-7-branch/gcc/xcoffout.c
    branches/gcc-7-branch/gcc/xcoffout.h