/* Process expressions for the GNU compiler for the Java(TM) language.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GCC.
static tree case_identity (tree, tree);
static unsigned char peek_opcode_at_pc (struct JCF *, int, int);
static int emit_init_test_initialization (void **entry, void * ptr);
-static int get_offset_table_index (tree);
static GTY(()) tree operand_type[59];
If a variable is on the quick stack, it means the value of variable
when the quick stack was last flushed. Conceptually, flush_quick_stack
- saves all the the quick_stack elements in parellel. However, that is
+ saves all the the quick_stack elements in parallel. However, that is
complicated, so it actually saves them (i.e. copies each stack value
to is home virtual register) from low indexes. This allows a quick_stack
element at index i (counting from the bottom of stack the) to references
case NEGATE_EXPR:
case ABS_EXPR:
case FLOAT_EXPR:
- case FFS_EXPR:
/* These don't change whether an object is nonzero or zero. */
return java_truthvalue_conversion (TREE_OPERAND (expr, 0));
flush_quick_stack (void)
{
int stack_index = stack_pointer;
- register tree prev, cur, next;
+ tree prev, cur, next;
/* First reverse the quick_stack, and count the number of slots it has. */
for (cur = quick_stack, prev = NULL_TREE; cur != NULL_TREE; cur = next)
decl = find_stack_slot (stack_index, type);
if (decl != node)
- expand_assignment (decl, node, 0, 0);
+ expand_assignment (decl, node, 0);
stack_index += 1 + TYPE_IS_WIDE (type);
}
}
}
-/* Pop and discrad the top COUNT stack slots. */
+/* Pop and discard the top COUNT stack slots. */
static void
java_stack_pop (int count)
decl1 = find_stack_slot (stack_pointer - 1, type1);
decl2 = find_stack_slot (stack_pointer - 2, type2);
temp = copy_to_reg (DECL_RTL (decl1));
- emit_move_insn (DECL_RTL (decl1), DECL_RTL (decl2));
- emit_move_insn (DECL_RTL (decl2), temp);
+ emit_move_insn (DECL_RTL (find_stack_slot (stack_pointer - 1, type2)),
+ DECL_RTL (decl2));
+ emit_move_insn (DECL_RTL (find_stack_slot (stack_pointer - 2, type1)), temp);
stack_type_map[stack_pointer - 1] = type2;
stack_type_map[stack_pointer - 2] = type1;
}
{
if (!flag_syntax_only && check)
{
- tree cond;
expr = save_expr (expr);
- cond = build (COND_EXPR, void_type_node,
+ expr = build (COND_EXPR, TREE_TYPE (expr),
build (EQ_EXPR, boolean_type_node, expr, null_pointer_node),
build (CALL_EXPR, void_type_node,
build_address_of (soft_nullpointer_node),
NULL_TREE, NULL_TREE),
- empty_stmt_node);
- expr = build (COMPOUND_EXPR, TREE_TYPE (expr), cond, expr);
+ expr);
}
return expr;
expand_assignment (build_java_arrayaccess (array,
rhs_type_node,
index),
- rhs_node, 0, 0);
+ rhs_node, 0);
}
/* Expand the evaluation of ARRAY[INDEX]. build_java_check_indexed_type makes
local_var = find_local_variable (local_var_index, int_type_node, pc);
constant_value = build_int_2 (ival, ival < 0 ? -1 : 0);
res = fold (build (PLUS_EXPR, int_type_node, local_var, constant_value));
- expand_assignment (local_var, res, 0, 0);
+ expand_assignment (local_var, res, 0);
}
tree base_type = promote_type (base_class);
if (base_type != TREE_TYPE (self_value))
self_value = fold (build1 (NOP_EXPR, base_type, self_value));
+ if (flag_indirect_dispatch
+ && output_class != self_class)
+ /* FIXME: output_class != self_class is not exactly the right
+ test. What we really want to know is whether self_class is
+ in the same translation unit as output_class. If it is,
+ we can make a direct reference. */
+ {
+ tree otable_index =
+ build_int_2 (get_symbol_table_index
+ (field_decl, &TYPE_OTABLE_METHODS (output_class)), 0);
+ tree field_offset =
+ build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class),
+ otable_index);
+ tree address
+ = fold (build (PLUS_EXPR,
+ build_pointer_type (TREE_TYPE (field_decl)),
+ self_value, field_offset));
+ return fold (build1 (INDIRECT_REF, TREE_TYPE (field_decl), address));
+ }
+
self_value = build_java_indirect_ref (TREE_TYPE (TREE_TYPE (self_value)),
self_value, check);
return fold (build (COMPONENT_REF, TREE_TYPE (field_decl),
optimizing class initialization. */
if (!STATIC_CLASS_INIT_OPT_P ())
DECL_BIT_INDEX(*init_test_decl) = -1;
+ /* Don't emit any symbolic debugging info for this decl. */
+ DECL_IGNORED_P (*init_test_decl) = 1;
}
init = build (CALL_EXPR, void_type_node,
tree func;
if (is_compiled_class (self_type))
{
- make_decl_rtl (method, NULL);
- func = build1 (ADDR_EXPR, method_ptr_type_node, method);
+ if (!flag_indirect_dispatch
+ || (!TREE_PUBLIC (method) && DECL_CONTEXT (method)))
+ {
+ make_decl_rtl (method, NULL);
+ func = build1 (ADDR_EXPR, method_ptr_type_node, method);
+ }
+ else
+ {
+ tree table_index =
+ build_int_2 (get_symbol_table_index
+ (method, &TYPE_ATABLE_METHODS (output_class)), 0);
+ func =
+ build (ARRAY_REF, method_ptr_type_node,
+ TYPE_ATABLE_DECL (output_class), table_index);
+ }
}
else
{
return dtable;
}
-/* Determine the index in the virtual offset table (otable) for a call to
- METHOD. If this method has not been seen before, it will be added to the
- otable_methods. If it has, the existing otable slot will be reused. */
+/* Determine the index in SYMBOL_TABLE for a reference to the decl
+ T. If this decl has not been seen before, it will be added to the
+ otable_methods. If it has, the existing table slot will be
+ reused. */
int
-get_offset_table_index (tree method)
+get_symbol_table_index (tree t, tree *symbol_table)
{
int i = 1;
tree method_list;
-
- if (otable_methods == NULL_TREE)
+
+ if (*symbol_table == NULL_TREE)
{
- otable_methods = build_tree_list (method, method);
+ *symbol_table = build_tree_list (t, t);
return 1;
}
- method_list = otable_methods;
+ method_list = *symbol_table;
while (1)
{
- if (TREE_VALUE (method_list) == method)
+ tree value = TREE_VALUE (method_list);
+ if (value == t)
return i;
i++;
if (TREE_CHAIN (method_list) == NULL_TREE)
method_list = TREE_CHAIN (method_list);
}
- TREE_CHAIN (method_list) = build_tree_list (method, method);
+ TREE_CHAIN (method_list) = build_tree_list (t, t);
return i;
}
if (flag_indirect_dispatch)
{
- otable_index = build_int_2 (get_offset_table_index (method), 0);
- method_index = build (ARRAY_REF, integer_type_node, otable_decl,
+ otable_index
+ = build_int_2 (get_symbol_table_index
+ (method, &TYPE_OTABLE_METHODS (output_class)), 0);
+ method_index = build (ARRAY_REF, integer_type_node,
+ TYPE_OTABLE_DECL (output_class),
otable_index);
}
else
if (flag_indirect_dispatch)
{
- otable_index = build_int_2 (get_offset_table_index (method), 0);
- idx = build (ARRAY_REF, integer_type_node, otable_decl, otable_index);
+ otable_index =
+ build_int_2 (get_symbol_table_index
+ (method, &TYPE_OTABLE_METHODS (output_class)), 0);
+ idx =
+ build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class),
+ otable_index);
}
else
{
if (FIELD_FINAL (field_decl))
{
if (DECL_CONTEXT (field_decl) != current_class)
- error_with_decl (field_decl,
- "assignment to final field `%s' not in field's class");
+ error ("%Jassignment to final field '%D' not in field's class",
+ field_decl, field_decl);
else if (FIELD_STATIC (field_decl))
{
if (!DECL_CLINIT_P (current_function_decl))
- warning_with_decl (field_decl,
- "assignment to final static field `%s' not in class initializer");
+ warning ("%Jassignment to final static field `%D' not in "
+ "class initializer", field_decl, field_decl);
}
else
{
tree cfndecl_name = DECL_NAME (current_function_decl);
if (! DECL_CONSTRUCTOR_P (current_function_decl)
&& !ID_FINIT_P (cfndecl_name))
- warning_with_decl (field_decl, "assignment to final field `%s' not in constructor");
+ warning ("%Jassignment to final field '%D' not in constructor",
+ field_decl, field_decl);
}
}
- expand_assignment (field_ref, new_value, 0, 0);
+ expand_assignment (field_ref, new_value, 0);
}
else
push_value (field_ref);
struct rtx_def *
java_expand_expr (tree exp, rtx target, enum machine_mode tmode,
- int modifier /* Actually an enum expand_modifier. */)
+ int modifier /* Actually an enum expand_modifier. */,
+ rtx *alt_rtl ATTRIBUTE_UNUSED)
{
tree current;
expand_decl (array_decl);
tmp = expand_assignment (array_decl,
build_new_array (element_type, length),
- 1, 0);
+ 1);
if (TREE_CONSTANT (init)
&& ilength >= 10 && JPRIMITIVE_TYPE_P (element_type))
{
expand_assignment (build (COMPONENT_REF, TREE_TYPE (data_fld),
build_java_indirect_ref (array_type,
array_decl, flag_check_references),
- data_fld), init, 0, 0);
+ data_fld), init, 0);
return tmp;
}
case BLOCK:
tree decl = BLOCK_EXPR_DECLS (catch);
tree type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE);
- expand_start_catch (type);
+ expand_start_catch (prepare_eh_table_type (type));
expand_expr_stmt (TREE_OPERAND (current, 0));
expand_end_catch ();
}
if (dead_code_index != -1)
{
/* We've just reached the end of a region of dead code. */
- warning ("unreachable bytecode from %d to before %d",
- dead_code_index, PC);
+ if (extra_warnings)
+ warning ("unreachable bytecode from %d to before %d",
+ dead_code_index, PC);
dead_code_index = -1;
}
}
if (pc == PC)
{
input_line = GET_u2 (linenumber_pointer - 2);
- emit_line_note (input_filename, input_line);
+ emit_line_note (input_location);
if (!(instruction_bits[PC] & BCODE_HAS_MULTI_LINENUMBERS))
break;
}
if (dead_code_index != -1)
{
/* We've just reached the end of a region of dead code. */
- warning ("unreachable bytecode from %d to the end of the method",
- dead_code_index);
+ if (extra_warnings)
+ warning ("unreachable bytecode from %d to the end of the method",
+ dead_code_index);
}
}
type = TREE_TYPE (value); \
decl = find_local_variable (var, type, oldpc); \
set_local_type (var, type ); \
- expand_assignment (decl, value, 0, 0); \
+ expand_assignment (decl, value, 0); \
}
#define STORE(OPERAND_TYPE, OPERAND_VALUE) \
{
if (flag_syntax_only)
return node;
- if (TREE_CODE_CLASS (TREE_CODE (node)) == '2')
- {
- if (TREE_SIDE_EFFECTS (TREE_OPERAND (node, 1)))
- TREE_OPERAND (node, 0) = save_expr (TREE_OPERAND (node, 0));
- }
- else if (TREE_CODE (node) == CALL_EXPR
- || TREE_CODE (node) == NEW_CLASS_EXPR
- || (TREE_CODE (node) == COMPOUND_EXPR
- && TREE_CODE (TREE_OPERAND (node, 0)) == CALL_EXPR
- && TREE_CODE (TREE_OPERAND (node, 1)) == SAVE_EXPR))
+ if (TREE_CODE (node) == CALL_EXPR
+ || TREE_CODE (node) == NEW_CLASS_EXPR
+ || (TREE_CODE (node) == COMPOUND_EXPR
+ && TREE_CODE (TREE_OPERAND (node, 0)) == CALL_EXPR
+ && TREE_CODE (TREE_OPERAND (node, 1)) == SAVE_EXPR))
{
tree arg, cmp;