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