PATCH some more small java compiler patches
Per Bothner
bothner@cygnus.com
Tue Feb 2 12:21:00 GMT 1999
I checked this into egcs.
--Per Bothner
Cygnus Solutions bothner@cygnus.com http://www.cygnus.com/~bothner
Tue Feb 2 10:39:47 1999 Per Bothner <bothner@cygnus.com>
Optimize: `return (a ? b : c)' as: `if (a) return b; else return c;'.
* jcf-write.c (generate_bytecode_return): New function.
(generate_bytecode_insns): Use it, for RETURN_EXPR.
* jcf-write.c (generate_bytecode_insns): For REAL_CST that is 0 or 1,
generate special [fd]const_[01] instructions.
* jcf-parse.c (yyparse): Don't emit_register_classes if -fsyntax-only.
* verify.c (verify_jvm_instructions): Do INVALIDATE_PC after
handling OPCODE_lookupswitch or OPCODE_tableswitch.
Index: jcf-write.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/java/jcf-write.c,v
retrieving revision 1.25
diff -u -p -r1.25 jcf-write.c
--- jcf-write.c 1999/02/02 10:16:56 1.25
+++ jcf-write.c 1999/02/02 20:17:22
@@ -1268,6 +1268,72 @@ call_cleanups (limit, state)
}
}
+void
+generate_bytecode_return (exp, state)
+ tree exp;
+ struct jcf_partial *state;
+{
+ tree return_type = TREE_TYPE (TREE_TYPE (state->current_method));
+ int returns_void = TREE_CODE (return_type) == VOID_TYPE;
+ int op;
+ again:
+ if (exp != NULL)
+ {
+ switch (TREE_CODE (exp))
+ {
+ case COMPOUND_EXPR:
+ generate_bytecode_insns (TREE_OPERAND (exp, 0), IGNORE_TARGET,
+ state);
+ exp = TREE_OPERAND (exp, 1);
+ goto again;
+ case COND_EXPR:
+ {
+ struct jcf_block *then_label = gen_jcf_label (state);
+ struct jcf_block *else_label = gen_jcf_label (state);
+ generate_bytecode_conditional (TREE_OPERAND (exp, 0),
+ then_label, else_label, 1, state);
+ define_jcf_label (then_label, state);
+ generate_bytecode_return (TREE_OPERAND (exp, 1), state);
+ define_jcf_label (else_label, state);
+ generate_bytecode_return (TREE_OPERAND (exp, 2), state);
+ }
+ return;
+ default:
+ generate_bytecode_insns (exp,
+ returns_void ? IGNORE_TARGET
+ : STACK_TARGET, state);
+ }
+ }
+ if (returns_void)
+ {
+ op = OPCODE_return;
+ call_cleanups (NULL_TREE, state);
+ }
+ else
+ {
+ op = OPCODE_ireturn + adjust_typed_op (return_type, 4);
+ if (state->num_finalizers > 0)
+ {
+ if (state->return_value_decl == NULL_TREE)
+ {
+ state->return_value_decl
+ = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
+ localvar_alloc (state->return_value_decl, state);
+ }
+ emit_store (state->return_value_decl, state);
+ call_cleanups (NULL_TREE, state);
+ emit_load (state->return_value_decl, state);
+ /* If we call localvar_free (state->return_value_decl, state),
+ 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
+ the greatest solution, but it is at least simple and safe. */
+ }
+ }
+ RESERVE (1);
+ OP1 (op);
+}
+
/* Generate bytecode for sub-expression EXP of METHOD.
TARGET is one of STACK_TARGET or IGNORE_TARGET. */
@@ -1362,20 +1428,26 @@ generate_bytecode_insns (exp, target, st
}
break;
case REAL_CST:
- offset = find_constant_index (exp, state);
- switch (TYPE_PRECISION (type))
- {
- case 32:
- push_constant1 (offset, state);
- NOTE_PUSH (1);
- break;
- case 64:
- push_constant2 (offset, state);
- NOTE_PUSH (2);
- break;
- default:
- abort ();
- }
+ {
+ int prec = TYPE_PRECISION (type) >> 5;
+ RESERVE(1);
+ if (real_zerop (exp))
+ OP1 (prec == 1 ? OPCODE_fconst_0 : OPCODE_dconst_0);
+ else if (real_onep (exp))
+ OP1 (prec == 1 ? OPCODE_fconst_1 : OPCODE_dconst_1);
+ /* FIXME Should also use fconst_2 for 2.0f.
+ Also, should use iconst_2/ldc followed by i2f/i2d
+ for other float/double when the value is a small integer. */
+ else
+ {
+ offset = find_constant_index (exp, state);
+ if (prec == 1)
+ push_constant1 (offset, state);
+ else
+ push_constant2 (offset, state);
+ }
+ NOTE_PUSH (prec);
+ }
break;
case STRING_CST:
push_constant1 (find_string_constant (&state->cpool, exp), state);
@@ -1651,39 +1723,14 @@ generate_bytecode_insns (exp, target, st
}
case RETURN_EXPR:
- if (!TREE_OPERAND (exp, 0))
- {
- op = OPCODE_return;
- call_cleanups (NULL_TREE, state);
- }
+ exp = TREE_OPERAND (exp, 0);
+ if (exp == NULL_TREE)
+ exp = empty_stmt_node;
+ else if (TREE_CODE (exp) != MODIFY_EXPR)
+ abort ();
else
- {
- exp = TREE_OPERAND (exp, 0);
- if (TREE_CODE (exp) != MODIFY_EXPR)
- abort ();
- exp = TREE_OPERAND (exp, 1);
- op = OPCODE_ireturn + adjust_typed_op (TREE_TYPE (exp), 4);
- generate_bytecode_insns (exp, STACK_TARGET, state);
- if (state->num_finalizers > 0)
- {
- if (state->return_value_decl == NULL_TREE)
- {
- state->return_value_decl
- = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
- localvar_alloc (state->return_value_decl, state);
- }
- emit_store (state->return_value_decl, state);
- call_cleanups (NULL_TREE, state);
- emit_load (state->return_value_decl, state);
- /* If we call localvar_free (state->return_value_decl, state),
- 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
- the greatest solution, but it is at least simple and safe. */
- }
- }
- RESERVE (1);
- OP1 (op);
+ exp = TREE_OPERAND (exp, 1);
+ generate_bytecode_return (exp, state);
break;
case LABELED_BLOCK_EXPR:
{
Index: jcf-parse.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/java/jcf-parse.c,v
retrieving revision 1.23
diff -u -p -r1.23 jcf-parse.c
--- jcf-parse.c 1999/01/23 20:46:51 1.23
+++ jcf-parse.c 1999/02/02 20:17:22
@@ -841,7 +841,7 @@ yyparse ()
}
java_expand_classes ();
- if (!java_report_errors () && !flag_emit_class_files)
+ if (!java_report_errors () && !flag_syntax_only)
emit_register_classes ();
return 0;
}
Index: verify.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/java/verify.c,v
retrieving revision 1.9
diff -u -p -r1.9 verify.c
--- verify.c 1999/01/23 21:49:54 1.9
+++ verify.c 1999/02/02 20:17:22
@@ -979,6 +979,7 @@ verify_jvm_instructions (jcf, byte_ops,
while (low++ <= high)
PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s4));
+ INVALIDATE_PC;
break;
}
@@ -1010,6 +1011,7 @@ verify_jvm_instructions (jcf, byte_ops,
last = match;
PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s4));
}
+ INVALIDATE_PC;
break;
}
More information about the Gcc-patches
mailing list