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]

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)





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