VerifierError with gcc trunk and ant 1.5.2
Andrew Haley
aph@redhat.com
Mon Mar 10 11:54:00 GMT 2003
Tom Tromey writes:
> >>>>> "Michael" == Michael Koch <konqueror@gmx.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);
More information about the Java
mailing list