Article View: gnu.gcc.bug
Article #1219Double arg passing bugs, gcc 2.2.2 for hppa1.1 (+fixes)
From: Mike Rendell
Date: Sat, 26 Sep 1992 16:29
Date: Sat, 26 Sep 1992 16:29
240 lines
8157 bytes
8157 bytes
Gcc 2.2.2 for hppa1.1 has two problems with passing double arguments:
one for varargs functions and one for functions whose fourth argument
is a double.
The first problem occurs when a double argument is passed as one of the
first three arguments to a varargs function: the value returned by
va_arg() is incorrect. The following program demonstrates the problem:
#include <stdio.h>
#include <stdarg.h>
void
foobar(char *str, ...)
{
va_list args;
va_start(args, str);
printf("%s %g\n", str, va_arg(args, double));
va_end(args);
}
void
main(void)
{
foobar("hi", 5.0);
}
The problem is that the function hppa_builtin_saveregs() in config/pa.c
flushes float registers %fr3,%fr4,%fr5,%fr6 and double registers %fr4,%fr6
instead of float registers %fr4,%fr5,%fr6,%fr7 and double registers
%fr5,%fr7. The following context diff for config/pa.c fixes the problem.
*** pa.c.orig Fri Sep 25 13:24:07 1992
--- pa.c Fri Sep 25 13:25:56 1992
***************
*** 2374,2392 ****
0, 0, OPTAB_LIB_WIDEN)));
/* Store fp registers. */
emit_move_insn (gen_rtx (MEM, SFmode, float_addr),
! gen_rtx (REG, SFmode, TARGET_SNAKE ? 60 : 39));
emit_move_insn (gen_rtx (MEM, SFmode, gen_rtx (PLUS, Pmode, float_addr,
gen_rtx (CONST_INT,
Pmode, 4))),
! gen_rtx (REG, SFmode, TARGET_SNAKE ? 58 : 38));
emit_move_insn (gen_rtx (MEM, SFmode, gen_rtx (PLUS, Pmode, float_addr,
gen_rtx (CONST_INT,
Pmode, 8))),
! gen_rtx (REG, SFmode, TARGET_SNAKE ? 56 : 37));
emit_move_insn (gen_rtx (MEM, SFmode, gen_rtx (PLUS, Pmode, float_addr,
gen_rtx (CONST_INT,
Pmode, 12))),
! gen_rtx (REG, SFmode, TARGET_SNAKE ? 54 : 36));
/*
* Allocate space for the double args, and store it in the
* __va_double member.
--- 2374,2392 ----
0, 0, OPTAB_LIB_WIDEN)));
/* Store fp registers. */
emit_move_insn (gen_rtx (MEM, SFmode, float_addr),
! gen_rtx (REG, SFmode, TARGET_SNAKE ? 62 : 39));
emit_move_insn (gen_rtx (MEM, SFmode, gen_rtx (PLUS, Pmode, float_addr,
gen_rtx (CONST_INT,
Pmode, 4))),
! gen_rtx (REG, SFmode, TARGET_SNAKE ? 60 : 38));
emit_move_insn (gen_rtx (MEM, SFmode, gen_rtx (PLUS, Pmode, float_addr,
gen_rtx (CONST_INT,
Pmode, 8))),
! gen_rtx (REG, SFmode, TARGET_SNAKE ? 58 : 37));
emit_move_insn (gen_rtx (MEM, SFmode, gen_rtx (PLUS, Pmode, float_addr,
gen_rtx (CONST_INT,
Pmode, 12))),
! gen_rtx (REG, SFmode, TARGET_SNAKE ? 56 : 36));
/*
* Allocate space for the double args, and store it in the
* __va_double member.
***************
*** 2409,2418 ****
/* Store fp registers as doubles. */
emit_move_insn (gen_rtx (MEM, DFmode, float_addr),
! (gen_rtx (REG, DFmode, TARGET_SNAKE ? 60 : 39)));
emit_move_insn (gen_rtx (MEM, DFmode, gen_rtx (PLUS, Pmode, float_addr,
gen_rtx (CONST_INT,
Pmode, 8))),
! gen_rtx (REG, DFmode, TARGET_SNAKE ? 56 : 37));
return copy_to_reg (XEXP (block, 0));
}
--- 2409,2418 ----
/* Store fp registers as doubles. */
emit_move_insn (gen_rtx (MEM, DFmode, float_addr),
! (gen_rtx (REG, DFmode, TARGET_SNAKE ? 62 : 39)));
emit_move_insn (gen_rtx (MEM, DFmode, gen_rtx (PLUS, Pmode, float_addr,
gen_rtx (CONST_INT,
Pmode, 8))),
! gen_rtx (REG, DFmode, TARGET_SNAKE ? 58 : 37));
return copy_to_reg (XEXP (block, 0));
}
The second problem occurs when a function's fourth argument is a double
and the preceeding three arguments are pointers/ints/shorts/chars.
The .EXPORT directive generated for such a function says the fourth
argument is in a register (ARG3=FR,ARG4=FU) when in fact it is not.
The following program demonstrates the problem:
int
blah(int a, int b, int c, double d)
{
return (int) d;
}
void
main(void)
{
blah(1, 2, 3, 4.0);
}
The result from gcc is:
% gcc -v -O t.c
Reading specs from /usr/local/lib/gcc-lib/hppa1.1-hp720-hpux/2.2.2/specs
gcc version 2.2.2
/usr/local/lib/gcc-lib/hppa1.1-hp720-hpux/2.2.2/cpp -lang-c -v -undef -D__GNUC__=2 -Dhppa -Dhp9000s800 -Dhp9000s700 -Dhp9k8 -DPWB -Dhpux -Dunix -D_HPUX_SOURCE -D__hppa__ -D__hp9000s800__ -D__hp9000s700__ -D__hp9k8__ -D__PWB__ -D__hpux__ -D__unix__ -D___HPUX_SOURCE__ -D__hppa -D__hp9000s800 -D__hp9000s700 -D__hp9k8 -D__PWB -D__hpux -D__unix -D___HPUX_SOURCE -D__OPTIMIZE__ t.c /usr/tmp/cca10054.i
GNU CPP version 2.2.2 (hp9000s800)
/usr/local/lib/gcc-lib/hppa1.1-hp720-hpux/2.2.2/cc1 /usr/tmp/cca10054.i -quiet -dumpbase t.c -O -version -o /usr/tmp/cca10054.s
GNU C version 2.2.2 (hp9000s800) compiled by GNU C version 2.2.2.
/usr/local/lib/gcc-lib/hppa1.1-hp720-hpux/2.2.2/as -o t.o /usr/tmp/cca10054.s
/usr/tmp/cca10054.s:14:Illegal argument description: 255
gcc: t.o: No such file or directory
% gcc -O -S t.c
% cat t.s
.SPACE $PRIVATE$
.SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
.SPACE $TEXT$
.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
.IMPORT $global$,DATA
.IMPORT $$dyncall,MILLICODE
; gcc_compiled.:
.SPACE $TEXT$
.SUBSPA $CODE$
.align 4
.EXPORT blah
.EXPORT blah,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=FR,ARGW4=FU,RTNVAL=GR
blah
.PROC
.CALLINFO FRAME=64,NO_CALLS
.ENTRY
copy 4,1
copy 30,4
stwm 1,64(0,30)
ldo -56(%r4),%r19
fldds 0(0,%r19),%fr4
fcnvfxt,dbl,sgl %fr4,%fr5
fstws %fr5,-16(30)
ldw -16(30),%r28
ldo 8(4),30
bv 0(2)
ldwm -8(30),4
.EXIT
.PROCEND
.IMPORT __main,CODE
.align 8
LC$0000
; .double 4.00000000000000000000e+00
.word 1074790400 ; = 0x40100000
.word 0 ; = 0x0
.align 4
.EXPORT main
.EXPORT main,PRIV_LEV=3,RTNVAL=GR
main
.PROC
.CALLINFO FRAME=128,CALLS,SAVE_RP
.ENTRY
stw 2,-20(0,30)
copy 4,1
copy 30,4
stwm 1,128(0,30)
.CALL
bl __main,2
nop
ldo -56(%r30),%r20
ldil L'LC$0000,%r19
ldo R'LC$0000(%r19),%r19
ldw 0(0,%r19),%r22
ldw 4(0,%r19),%r23
stw %r22,-16(0,30)
stw %r23,-12(0,30)
fldds -16(0,30),%fr4
fstds %fr4,0(0,%r20)
ldo 1(0),%r26
ldo 2(0),%r25
ldo 3(0),%r24
.CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
bl blah,2
nop
ldo 8(4),30
ldw -28(0,30),2
bv 0(2)
ldwm -8(30),4
.EXIT
.PROCEND
Note the .EXPORT line for blah says the fourth argument is in a register while
the code for blah takes the argument from the stack. The problem is in the
ASM_DECLARE_FUNCTION_NAME macro in config/pa.h which does an alignment check
for a double in the second argument, but not the fourth. If a double is in
the fourth argument, nothing should be printed. The following context diff
for config/pa.h fixes the problem (note that i must be incremented to 4
when i == 3 since it is used later in the macro).
*** pa.h.orig Sat Sep 26 10:50:26 1992
--- pa.h Sat Sep 26 10:53:09 1992
***************
*** 783,789 ****
fprintf (FILE, ",ARGW%d=FR", i++); \
else if (TYPE_MODE (DECL_ARG_TYPE (parm)) == DFmode) \
{ \
! if (i == 1) i++; \
ASM_DOUBLE_ARG_DESCRIPTORS (FILE, i++, i++); \
} \
else \
--- 783,793 ----
fprintf (FILE, ",ARGW%d=FR", i++); \
else if (TYPE_MODE (DECL_ARG_TYPE (parm)) == DFmode) \
{ \
! if (i & 1) \
! { \
! i++; \
! if (i == 4) break; \
! } \
ASM_DOUBLE_ARG_DESCRIPTORS (FILE, i++, i++); \
} \
else \
--
Michael Rendell - Dept. of Comp. Sci., Memorial University of Newfoundland
Technical Details
Message-ID:
<1992Sep26.162900.22800@cs.mun.ca>Path:
arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!garfield.cs.mun.ca!michaelShow Full Headers
Complete Article Headers
Newsgroups: gnu.gcc.bug Path: arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!garfield.cs.mun.ca!michael From: michael@garfield.cs.mun.ca (Mike Rendell) Subject: Double arg passing bugs, gcc 2.2.2 for hppa1.1 (+fixes) Message-ID: <1992Sep26.162900.22800@cs.mun.ca> Sender: gnulists@ai.mit.edu Organization: CS Dept., Memorial University of Newfoundland Distribution: gnu Date: Sat, 26 Sep 1992 16:29:00 GMT Approved: bug-gcc@prep.ai.mit.edu Lines: 241