This is the mail archive of the gcc-bugs@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]

[Bug target/36800] New: va_arg for _Decimal128 on 32-bit Power mishandled in certain cases


The following fails on 32-bit hard-float powerpc*-*-linux* (tested for trunk,
code inspection indicates present for 4.3 as well).

#include <stdarg.h>
extern void abort (void);

void
f (int a, ...)
{
  va_list ap;
  if (a != 0)
    abort ();
  va_start (ap, a);
  if (va_arg (ap, _Decimal128) != 1.2DL)
    abort ();
  if (va_arg (ap, _Decimal128) != 2.34DL)
    abort ();
  if (va_arg (ap, _Decimal128) != 3.456DL)
    abort ();
  if (va_arg (ap, _Decimal128) != 4.567DL)
    abort ();
  if (va_arg (ap, double) != 5.125)
    abort ();
  va_end (ap);
}

int
main (void)
{
  f (0, 1.2DL, 2.34DL, 3.456DL, 4.567DL, 5.125);
  return 0;
}

Suppose some arguments are passed in floating-point registers using all but
f8 and maybe f7 of the registers available for floating-point arguments.
Suppose the next argument is _Decimal128, so is passed on the stack because
an aligned pair of registers is not available, and that this _Decimal128
argument is one of the variable arguments in a call to a variadic function,
and that a following argument is one that would fit in a single floating-point
register if the _Decimal128 argument hadn't forced all subsequent
floating-point arguments to go on the stack.

Then the code to ensure that subsequent va_arg calls after the one getting
that _Decimal128 argument do not look in the saved floating-point
registers

      if ((n_reg == 2 && !regalign) || n_reg > 2)
        {
          /* Ensure that we don't find any more args in regs.
             Alignment has taken care of for special cases.  */
          t = build_gimple_modify_stmt (reg,
                                        build_int_cst (TREE_TYPE (reg), 8));
          gimplify_and_add (t, pre_p);
        }

does not trigger because regalign is set.  But unlike the alignment for
pairs of GPRs, the alignment here sets fpr to 7 leaving a subsequent va_arg
call thinking it can take a value from f8.

I think the fix is simply not to set regalign in this case, but I haven't
tested this.


-- 
           Summary: va_arg for _Decimal128 on 32-bit Power mishandled in
                    certain cases
           Product: gcc
           Version: 4.4.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: jsm28 at gcc dot gnu dot org
GCC target triplet: powerpc*-*-linux*


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36800


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