This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: VerifierError with gcc trunk and ant 1.5.2


Tom Tromey writes:
 > >>>>> "Michael" == Michael Koch <konqueror at gmx dot de> writes:
 > 
 > Michael> Here it is. I hope this helps.
 > 
 > I took a very brief look at this.  Given where the error occurs, I
 > think this is probably a known gcj code generation bug.  We don't
 > correctly keep variables live across subroutines.  This can lead to
 > unverifiable output.
 > 
 > I think Andrew has a patch for this.

I do -- it's simple, crude, and it works.

If we emit a jsr, we cannot free any of our local state variables
unless we can prove that it's safe to do so.  We can't prove such a
thing, so don't free them.

This has the disadvantage of wasting some local variable space.
However, it is far better than what we do at the moment, which is
silently generate incorrect code.

Andrew.

Index: jcf-write.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-write.c,v
retrieving revision 1.120
diff -u -r1.120 jcf-write.c
--- jcf-write.c	29 Jan 2003 01:19:40 -0000	1.120
+++ jcf-write.c	11 Feb 2003 13:44:16 -0000
@@ -279,6 +279,9 @@
 
   /* Information about the current switch statement. */
   struct jcf_switch_state *sw_state;
+
+  /* The count of jsr instructions that have been emmitted.  */
+  long num_jsrs;
 };
 
 static void generate_bytecode_insns (tree, int, struct jcf_partial *);
@@ -293,7 +296,7 @@
 static struct jcf_block * get_jcf_label_here (struct jcf_partial *);
 static void put_linenumber (int, struct jcf_partial *);
 static void localvar_alloc (tree, struct jcf_partial *);
-static void localvar_free (tree, struct jcf_partial *);
+static void maybe_free_localvar (tree, struct jcf_partial *, int);
 static int get_access_flags (tree);
 static void write_chunks (FILE *, struct chunk *);
 static int adjust_typed_op (tree, int);
@@ -600,7 +603,7 @@
 }
 
 static void
-localvar_free (tree decl, struct jcf_partial *state)
+maybe_free_localvar (tree decl, struct jcf_partial *state, int really)
 {
   struct jcf_block *end_label = get_jcf_label_here (state);
   int index = DECL_LOCAL_INDEX (decl);
@@ -612,6 +615,8 @@
 
   if (info->decl != decl)
     abort ();
+  if (! really)
+    return;
   ptr[0] = NULL;
   if (wide)
     {
@@ -1065,6 +1070,7 @@
   OP1 (OPCODE_jsr);
   /* Value is 1 byte from reloc back to start of instruction.  */
   emit_reloc (RELOCATION_VALUE_1, OPCODE_jsr_w, target, state);
+  state->num_jsrs++;
 }
 
 /* Generate code to evaluate EXP.  If the result is true,
@@ -1346,7 +1352,7 @@
 	  emit_store (state->return_value_decl, state);
 	  call_cleanups (NULL, state);
 	  emit_load (state->return_value_decl, state);
-	  /* If we call localvar_free (state->return_value_decl, state),
+	  /* If we call maybe_free_localvar (state->return_value_decl, state, 1),
 	     then we risk the save decl erroneously re-used in the
 	     finalizer.  Instead, we keep the state->return_value_decl
 	     allocated through the rest of the method.  This is not
@@ -1383,6 +1389,7 @@
 	{
 	  tree local;
 	  tree body = BLOCK_EXPR_BODY (exp);
+	  long jsrs = state->num_jsrs;
 	  for (local = BLOCK_EXPR_DECLS (exp); local; )
 	    {
 	      tree next = TREE_CHAIN (local);
@@ -1396,10 +1403,11 @@
 	      body = TREE_OPERAND (body, 1);
 	    }
 	  generate_bytecode_insns (body, target, state);
+	  
 	  for (local = BLOCK_EXPR_DECLS (exp); local; )
 	    {
 	      tree next = TREE_CHAIN (local);
-	      localvar_free (local, state);
+	      maybe_free_localvar (local, state, state->num_jsrs <= jsrs);
 	      local = next;
 	    }
 	}
@@ -2353,8 +2361,8 @@
 	if (CAN_COMPLETE_NORMALLY (finally))
 	  {
 	    maybe_wide (OPCODE_ret, DECL_LOCAL_INDEX (return_link), state);
-	    localvar_free (exception_decl, state);
-	    localvar_free (return_link, state);
+	    maybe_free_localvar (exception_decl, state, 1);
+	    maybe_free_localvar (return_link, state, 1);
 	    define_jcf_label (finished_label, state);
 	  }
       }
@@ -2951,6 +2965,7 @@
 	  get_jcf_label_here (state);  /* Force a first block. */
 	  for (t = DECL_ARGUMENTS (part);  t != NULL_TREE;  t = TREE_CHAIN (t))
 	    localvar_alloc (t, state);
+	  state->num_jsrs = 0;
 	  generate_bytecode_insns (body, IGNORE_TARGET, state);
 	  if (CAN_COMPLETE_NORMALLY (body))
 	    {
@@ -2960,9 +2975,9 @@
 	      OP1 (OPCODE_return);
 	    }
 	  for (t = DECL_ARGUMENTS (part);  t != NULL_TREE;  t = TREE_CHAIN (t))
-	    localvar_free (t, state);
+	    maybe_free_localvar (t, state, 1);
 	  if (state->return_value_decl != NULL_TREE)
-	    localvar_free (state->return_value_decl, state);
+	    maybe_free_localvar (state->return_value_decl, state, 1);
 	  finish_jcf_block (state);
 	  perform_relocations (state);


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