stdcall/reg-stack patch (from Tim Josling)
Mumit Khan
khan@xraylith.wisc.EDU
Wed Feb 24 09:03:00 GMT 1999
This patch, from Tim Josling <tej@melbpc.org.au>, fixes a gcc x86
codegen bug for stdcall functions returning values in fp registers.
This bug pretty much eliminates GCC as a choice when building Java
JNI (and loadable modules for various other applications) on windows32
platform.
For my original bug report and testcase, see:
http://www.cygnus.com/ml/egcs-bugs/1998-Oct/0773.html
(unfortunately, the HTML'd version on the ml archive looks munged. I
can always forward a copy of the original report).
For Tim Josling's patch and analysis posted to egcs-bugs recently, see:
http://egcs.cygnus.com/ml/egcs-bugs/1999-02/msg00437.html
I've taken Tim's changes from his posting to egcs-bugs, made some minor
style modifications, and created a diff against egcs 1999-02-14.
egcs-1.1.2-pre1 and 1999-02-14 bootstraps and testsuites show no
regressions; built/tested on i686-pc-linux-gnu, i586-pc-cygwin32 and
i386-mingw32 (yes, I'm very interested in this fix ;-).
Tue Feb 23 20:19:28 1999 Tim Josling <tej@melbpc.org.au>
* reg-stack.cc (rtx_contains_return): New function.
(stack_reg_life_analysis): Use.
Index: gcc/reg-stack.c
===================================================================
RCS file: /homes/khan/src/CVSROOT/egcs-dev/gcc/reg-stack.c,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 reg-stack.c
--- gcc/reg-stack.c 1999/02/21 20:03:15 1.1.1.1
+++ gcc/reg-stack.c 1999/02/24 02:16:59
@@ -1137,6 +1137,52 @@ stack_result (decl)
return result != 0 && STACK_REG_P (result) ? result : 0;
}
+/* 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. */
+
+static int
+rtx_contains_return (insn, check_jump_flag)
+ 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)
+ {
+ /* found a nested return. DLLs will now return double. */
+ return 1;
+ }
+ }
+
+ /* not a return. */
+ return 0;
+}
+
/* Determine the which registers are live at the start of each basic
block of the function whose first insn is FIRST.
@@ -1179,21 +1225,19 @@ stack_reg_life_analysis (first, stackent
rtx retvalue;
if ((retvalue = stack_result (current_function_decl)))
- {
- /* Find all RETURN insns and mark them. */
+ {
+ /* 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);
-
- /* Mark off the end of last block if we "fall off" the end of the
- function into the epilogue. */
-
- 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);
- }
+ for (block = blocks - 1; --block >= 0; )
+ if (rtx_contains_return (block_end[block], 1))
+ mark_regs_pat (retvalue, block_out_reg_set+block);
+
+ /* Mark off the end of last block if we "fall off" the end of the
+ function into the epilogue. */
+
+ if (rtx_contains_return (block_end[blocks-1], 0))
+ mark_regs_pat (retvalue, block_out_reg_set+blocks-1);
+ }
}
/* now scan all blocks backward for stack register use */
More information about the Gcc-patches
mailing list