diff options
Diffstat (limited to 'gcc/java/jcf-write.c')
-rw-r--r-- | gcc/java/jcf-write.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/gcc/java/jcf-write.c b/gcc/java/jcf-write.c index b4a9e1b..097177e 100644 --- a/gcc/java/jcf-write.c +++ b/gcc/java/jcf-write.c @@ -2149,7 +2149,37 @@ generate_bytecode_insns (tree exp, int target, struct jcf_partial *state) } break; case SAVE_EXPR: - generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state); + /* Because the state associated with a SAVE_EXPR tree node must + be a RTL expression, we use it to store the DECL_LOCAL_INDEX + of a temporary variable in a CONST_INT. */ + if (! SAVE_EXPR_RTL (exp)) + { + tree type = TREE_TYPE (exp); + tree decl = build_decl (VAR_DECL, NULL_TREE, type); + generate_bytecode_insns (TREE_OPERAND (exp, 0), + STACK_TARGET, state); + localvar_alloc (decl, state); + SAVE_EXPR_RTL (exp) = GEN_INT (DECL_LOCAL_INDEX (decl)); + emit_dup (TYPE_IS_WIDE (type) ? 2 : 1, 0, state); + emit_store (decl, state); + } + else + { + /* The following code avoids creating a temporary DECL just + to pass to emit_load. This code could be factored with + the similar implementation in emit_load_or_store. */ + tree type = TREE_TYPE (exp); + int kind = adjust_typed_op (type, 4); + int index = (int) INTVAL (SAVE_EXPR_RTL (exp)); + if (index <= 3) + { + RESERVE (1); /* [ilfda]load_[0123] */ + OP1 (OPCODE_iload + 5 + 4*kind + index); + } + else /* [ilfda]load */ + maybe_wide (OPCODE_iload + kind, index, state); + NOTE_PUSH (TYPE_IS_WIDE (type) ? 2 : 1); + } break; case CONVERT_EXPR: case NOP_EXPR: |