Thread View: gnu.gcc.bug
1 messages
1 total messages
Started by Mike Rendell
Sat, 26 Sep 1992 16:29
Double arg passing bugs, gcc 2.2.2 for hppa1.1 (+fixes)
Author: 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
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads