This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
No Subject
I declare it as __stdcall (=JNICALL) to allow it to be used as a dll
and called by Sun's Java Virtual Machine. The function is measn to
return a float reult, but instead the floating point stack is empty.
Source code (see 1). Output (see 2).
Source without stdcall (see 3). Output (see 4).
egcs version:
egcs-2.91.57 1990901 (egcs-1-1 release).
GCC command:
gcc -Wall -S badcodeBAD.c -o badcodeBAD.s
Environment
Windows 95-OSR2 with usb patch..
Cygwin-b20.1
I traced the problem down to a bug in reg-stack.c. See 5 for the patch.
The problem is that in routine stack_reg_life_analysis it tries to check
if the block does a return from the function by checking if the last
insn of each block is a jump with return, or for the last block any
instruction with return. However in a stdcall function, the return
instruction is a PARALLEL with the return under the parallel so the code
does not find it (see 6). See 7 for the code after reg-stack has
finished with it - the return register is marked 'dead'.
The patch looks further into the parallel to find the return if it's
there. I have verified the patch fixed my problem and recompiles GCC ok.
I can reproduce the problem at will and generate the patch in another
fornat f that would help.
Tim Josling
tej@melbpc.org.au
1. Source code (this was not my original source code but this is the
minimal case to produce the problem)
__stdcall float Java_com_josling_mytest_mytest_test
(void * e, void * o, void * a) {
float f=6.78;
return f;
}
2. Assembler output - note the fstp which pops the result
.file "badcodeBad.c"
gcc2_compiled.:
___gnu_compiled_c:
.text
.align 4
.globl _Java_com_josling_mytest_mytest_test@12
.def _Java_com_josling_mytest_mytest_test@12; .scl 2; .type 32; .endef
_Java_com_josling_mytest_mytest_test@12:
pushl %ebp
movl %esp,%ebp
subl $16,%esp
movl $1087960515,-4(%ebp)
flds -4(%ebp)
fstp %st(0)
jmp L1
.p2align 4,,7
L1:
movl %ebp,%esp
popl %ebp
ret $12
3. Source code without the stdcall
/*__stdcall*/ float Java_com_josling_mytest_mytest_test
(void * e, void * o, void * a) {
float f=6.78;
return f;
}
4. Output from the source code without the stdcall
.file "badcodeOK.c"
gcc2_compiled.:
___gnu_compiled_c:
.text
.align 4
.globl _Java_com_josling_mytest_mytest_test
.def _Java_com_josling_mytest_mytest_test; .scl 2; .type 32; .endef
_Java_com_josling_mytest_mytest_test:
pushl %ebp
movl %esp,%ebp
subl $16,%esp
movl $1087960515,-4(%ebp)
flds -4(%ebp)
jmp L1
.p2align 4,,7
L1:
movl %ebp,%esp
popl %ebp
ret
5. Patch to reg-stack.c (< is the new code).
275d274
< static int rtx_contains_return PROTO((rtx, int));
1437,1481d1435
< /* Check if instruction is or contains a return.
<
< With the stdcall option the return rtx becomea a parallel
< containing the return
<
< if check_jump_flag is on, it also checks that it is a jump
<
< Returns
<
< 0 = false
< 1 = true
<
< */
<
< static int
< rtx_contains_return(rtx insn, int check_jump_flag ) {
< int i;
< rtx body;
<
< /* Check for non-jump and so not a return */
< if (GET_CODE(insn)!=JUMP_INSN) {
< if (check_jump_flag) return 0;
< }
<
< body=PATTERN(insn);
<
< /* Standard return pattern */
< if (GET_CODE (body) == RETURN) return 1;
<
< /* If not parallel here, we have run out of possibilities */
< if (GET_CODE (body)!= PARALLEL) return 0;
<
< /* We have a parallel set here jump. Check for a return in the
vector */
<
< for (i = 0; i < XVECLEN (body, 0); i++) {
< if (GET_CODE (XVECEXP (body, 0, i)) == RETURN) {
< return 1; /* found a nested return. DLLs will now return double
*/
< }
< }
<
< /* not a return */
< return 0;
< }
<
<
1524,1529c1478,1484
< {
< /* Find all RETURN insns and mark them. */
<
< for (block = blocks - 1; --block >= 0;)
< if (rtx_contains_return(block_end[block],1))
< mark_regs_pat (retvalue, block_out_reg_set+block);
---
> {
> /* Find all RETURN insns and mark them. */
>
> for (block = blocks - 1; --block >= 0;)
> if (GET_CODE (block_end[block]) == JUMP_INSN
> && GET_CODE (PATTERN (block_end[block])) == RETURN)
> mark_regs_pat (retvalue, block_out_reg_set+block);
1534,1535c1489,1491
< if (rtx_contains_return(block_end[blocks-1],0))
< mark_regs_pat (retvalue, block_out_reg_set+blocks-1);
---
> if (GET_CODE (block_end[blocks-1]) != JUMP_INSN
> || GET_CODE (PATTERN (block_end[blocks-1])) == RETURN)
> mark_regs_pat (retvalue, block_out_reg_set+blocks-1);
6. badcodeBAD.c.greg (rtx before reg-stack.c got involved - see
instruction 30 at the end with the return under the parallel).
;; Function Java_com_josling_mytest_mytest_test
;; Register dispositions:
21 in 9
;; Hard regs used: 6 8 9 16
(note 2 0 23 "" NOTE_INSN_DELETED)
;; Insn is not within a basic block
(insn 23 2 25 (set (mem:SI (pre_dec:SI (reg:SI 7 %esp)))
(reg:SI 6 %ebp)) -1 (nil)
(nil))
;; Insn is not within a basic block
(insn 25 23 26 (set (reg:SI 6 %ebp)
(reg:SI 7 %esp)) -1 (nil)
(nil))
;; Insn is not within a basic block
(insn 26 25 22 (parallel[
(set (reg:SI 7 %esp)
(minus:SI (reg:SI 7 %esp)
(const_int 16)))
(set (reg:SI 6 %ebp)
(unspec:SI[
(reg:SI 6 %ebp)
] 4))
] ) -1 (nil)
(nil))
(note 22 26 3 "" NOTE_INSN_PROLOGUE_END)
(note 3 22 4 "" NOTE_INSN_FUNCTION_BEG)
(note 4 3 6 "" NOTE_INSN_DELETED)
(note 6 4 8 0 NOTE_INSN_BLOCK_BEG)
;; Insn is not within a basic block
(insn 8 6 10 (set (mem:SF (plus:SI (reg:SI 6 %ebp)
(const_int -4)))
(const_double:SF (const_int 0) 0 -1023410176 1073862901)) 70
{movsf+1} (nil)
(nil))
;; Insn is not within a basic block
(insn 10 8 12 (set (reg:DF 9 %st(1))
(float_extend:DF (mem:SF (plus:SI (reg:SI 6 %ebp)
(const_int -4))))) 105 {extendsfdf2} (nil)
(nil))
;; Insn is not within a basic block
(insn 12 10 13 (set (reg/i:DF 8 %st(0))
(reg:DF 9 %st(1))) 75 {movdf+1} (nil)
(nil))
;; Insn is not within a basic block
(insn 13 12 14 (use (reg/i:DF 8 %st(0))) -1 (nil)
(nil))
;; Insn is not within a basic block
(jump_insn 14 13 15 (set (pc)
(label_ref 20)) 282 {jump} (nil)
(nil))
(barrier 15 14 17)
(note 17 15 18 0 NOTE_INSN_BLOCK_END)
(note 18 17 20 "" NOTE_INSN_FUNCTION_END)
;; Insn is not within a basic block
(code_label 20 18 21 1 "")
(note 21 20 31 "" NOTE_INSN_DELETED)
(note 31 21 28 "" NOTE_INSN_EPILOGUE_BEG)
;; Insn is not within a basic block
(insn 28 31 29 (parallel[
(set (reg:SI 7 %esp)
(reg:SI 6 %ebp))
(clobber (reg:SI 6 %ebp))
] ) -1 (nil)
(nil))
;; Insn is not within a basic block
(insn 29 28 30 (parallel[
(set (reg:SI 6 %ebp)
(mem:SI (reg:SI 7 %esp)))
(set (reg:SI 7 %esp)
(plus:SI (reg:SI 7 %esp)
(const_int 4)))
] ) -1 (nil)
(nil))
;; Insn is not within a basic block
(jump_insn 30 29 27 (parallel[
(return)
(use (const_int 12))
] ) -1 (nil)
(nil))
(barrier 27 30 0)
7. badcodeBAD.c.stack - rtx after reg-stack has mangled it - note the
dead register on insn 33 which should be the return value.
;; Function Java_com_josling_mytest_mytest_test
(note 2 0 24 "" NOTE_INSN_DELETED)
;; Insn is not within a basic block
(insn 24 2 26 (set (mem:SI (pre_dec:SI (reg:SI 7 %esp)))
(reg:SI 6 %ebp)) -1 (nil)
(nil))
;; Insn is not within a basic block
(insn 26 24 27 (set (reg:SI 6 %ebp)
(reg:SI 7 %esp)) -1 (nil)
(nil))
;; Insn is not within a basic block
(insn 27 26 23 (parallel[
(set (reg:SI 7 %esp)
(minus:SI (reg:SI 7 %esp)
(const_int 16)))
(set (reg:SI 6 %ebp)
(unspec:SI[
(reg:SI 6 %ebp)
] 4))
] ) -1 (nil)
(nil))
(note 23 27 3 "" NOTE_INSN_PROLOGUE_END)
(note 3 23 4 "" NOTE_INSN_FUNCTION_BEG)
(note 4 3 6 "" NOTE_INSN_DELETED)
(note 6 4 8 0 NOTE_INSN_BLOCK_BEG)
;; Insn is not within a basic block
(insn 8 6 11 (set (mem:SF (plus:SI (reg:SI 6 %ebp)
(const_int -4)))
(const_double:SF (const_int 0) 0 -1023410176 1073862901)) 70
{movsf+1} (nil)
(nil))
;; Insn is not within a basic block
(insn:QI 11 8 13 (set (reg:SF 8 %st(0))
(mem:SF (plus:SI (reg:SI 6 %ebp)
(const_int -4)))) 70 {movsf+1} (nil)
(nil))
(note:QI 13 11 33 "" NOTE_INSN_DELETED)
;; Insn is not within a basic block
(insn:QI 33 13 14 (set (reg:DF 8 %st(0))
(reg:DF 8 %st(0))) -1 (nil)
(expr_list:REG_DEAD (reg:DF 8 %st(0))
(nil)))
;; Insn is not within a basic block
(insn:QI 14 33 15 (use (reg/i:SF 8 %st(0))) -1 (nil)
(nil))
;; Insn is not within a basic block
(jump_insn 15 14 16 (set (pc)
(label_ref 21)) 282 {jump} (nil)
(nil))
(barrier 16 15 18)
(note 18 16 19 0 NOTE_INSN_BLOCK_END)
(note 19 18 21 "" NOTE_INSN_FUNCTION_END)
;; Insn is not within a basic block
(code_label 21 19 22 1 "")
(note 22 21 32 "" NOTE_INSN_DELETED)
(note 32 22 29 "" NOTE_INSN_EPILOGUE_BEG)
;; Insn is not within a basic block
(insn 29 32 30 (parallel[
(set (reg:SI 7 %esp)
(reg:SI 6 %ebp))
(clobber (reg:SI 6 %ebp))
] ) -1 (nil)
(nil))
;; Insn is not within a basic block
(insn 30 29 31 (parallel[
(set (reg:SI 6 %ebp)
(mem:SI (reg:SI 7 %esp)))
(set (reg:SI 7 %esp)
(plus:SI (reg:SI 7 %esp)
(const_int 4)))
] ) -1 (nil)
(nil))
;; Insn is not within a basic block
(jump_insn 31 30 28 (parallel[
(return)
(use (const_int 12))
] ) -1 (nil)
(nil))
(barrier 28 31 0)