This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: Strange, elusive bug in boolean return values with latest fetch from cvs
Okay, so I can duplicate your test case!
Here's a partial patch. Its result is:
.globl BugJune3.seeIfItsTrue() .globl BugJune3.seeIfItsTrue()
.type BugJune3.seeIfItsTrue(), @function .type BugJune3.seeIfItsTrue(), @function
BugJune3.seeIfItsTrue(): BugJune3.seeIfItsTrue():
.LFB3: .LFB3:
pushq %rbp pushq %rbp
.LCFI5: .LCFI5:
movq 8(%rdi), %rdi movq 8(%rdi), %rdi
> xorl %eax, %eax
movq %rsp, %rbp movq %rsp, %rbp
.LCFI6: .LCFI6:
testq %rdi, %rdi testq %rdi, %rdi
je .L3 | je .L5
.L4: | .L3:
movq (%rdi), %rax movq (%rdi), %rax
call *56(%rax) call *56(%rax)
.L3: | movzbl %al, %eax
> .L5:
leave leave
xorl %eax, %eax <
ret ret
.LFE3: .LFE3:
.size BugJune3.seeIfItsTrue(), .-_ZN8BugJune31 .size BugJune3.seeIfItsTrue(), .-_ZN8BugJune31
The problem seems to be due to the fact that the type system of the
Java Virtual Machine is subtly different from the type system of the
Java Programming Language. In particular, booleans and ints are
incompatible in the source language but are both treated as integer
types in the VM. So, treating these as distinct types when compiling
bytecode is incorrect.
What we do at the moment is basically wrong, in that if we have two
sources and one destination, and one source is int and the other
boolean, then they are treated as distinct variables.
Look at this fragment:
7: iconst_0
8: goto 18
11: aload_0
12: getfield #4=<Field BugJune3.littleThing BugJune3$LittleThing>
15: invokevirtual #5=<Method BugJune3$LittleThing.isTrue ()boolean>
18: ireturn
insn 7 pushes an int, and insn 15 pushes a boolean. insn 18 returns
something, and the compiler doesn't believe that these types are
compatible. So, when the compiler wants a temporary to hold the
result of insn 15, it generates a new one instead of using the same
one that was generated for insn 7. And, of course, that value is
lost.
So, when we create a temporary for an item on the evaluation stack, we
need to create an int, even if the insn that created it returned a
boolean.
This patch forces all pushes of booleans onto the operand stack to be
converted to ints. I don't think it is totally correct, but it's
better.
I have't tested it at all: see how you get on.
Andrew.
2004-06-09 Andrew Haley <aph@redhat.com>
* expr.c (flush_quick_stack): Perform type conversion when
building our MODIFY_EXPR.
(push_type_0): Treat booleans pushed onto the stack as ints.
(push_value): Likewise.
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.192
diff -p -2 -c -w -r1.192 expr.c
*** expr.c 8 Jun 2004 13:27:38 -0000 1.192
--- expr.c 9 Jun 2004 19:04:32 -0000
*************** flush_quick_stack (void)
*** 240,244 ****
--- 240,248 ----
decl = find_stack_slot (stack_index, type);
if (decl != node)
+ {
+ if (TREE_TYPE (node) != TREE_TYPE (decl))
+ decl = convert (TREE_TYPE (node), decl);
java_add_stmt (build (MODIFY_EXPR, TREE_TYPE (node), decl, node));
+ }
stack_index += 1 + TYPE_IS_WIDE (type);
}
*************** push_type_0 (tree type)
*** 253,256 ****
--- 257,264 ----
int n_words;
type = promote_type (type);
+ /* Although Java local variables may be of boolean type, the Java VM
+ treats them as though they're integers. */
+ if (type == promoted_boolean_type_node)
+ type = int_type_node;
n_words = 1 + TYPE_IS_WIDE (type);
if (stack_pointer + n_words > DECL_MAX_STACK (current_function_decl))
*************** push_value (tree value)
*** 277,280 ****
--- 285,292 ----
{
type = promote_type (type);
+ /* Although Java local variables may be of boolean type, the Java VM
+ treats them as though they're integers. */
+ if (type == promoted_boolean_type_node)
+ type = int_type_node;
value = convert (type, value);
}