aboutsummaryrefslogtreecommitdiff
path: root/gcc/java/expr.c
diff options
context:
space:
mode:
authorBryce McKinlay <bryce@gcc.gnu.org>2002-02-28 11:40:29 +0000
committerBryce McKinlay <bryce@gcc.gnu.org>2002-02-28 11:40:29 +0000
commit022dcc46051ffd0114ac3382cc7e50928f17d995 (patch)
tree6daf1252f43021f81274da35d2f5f16541eaedb2 /gcc/java/expr.c
parent70da1d030dfa76bd605100e3969df62b6aaa2512 (diff)
downloadgcc-022dcc46051ffd0114ac3382cc7e50928f17d995.zip
gcc-022dcc46051ffd0114ac3382cc7e50928f17d995.tar.gz
gcc-022dcc46051ffd0114ac3382cc7e50928f17d995.tar.bz2
expr.c (java_array_data_offset): Removed function.
* expr.c (java_array_data_offset): Removed function. (JAVA_ARRAY_LENGTH_OFFSET): Removed macro. (build_java_array_length_access): Obtain "length" value using a COMPONENT_REF, instead of INDIRECT_REF and arithmetic. (build_java_arrayaccess): Correct comment. Access "data" using a COMPONENT_REF, and return an ARRAY_REF instead of an INDIRECT_REF. (build_java_arraystore_check): New function. (expand_java_arraystore): Use build_java_arraystore_check. * parse.y (patch_assignment): Simplify code to insert a store check when lvalue is an ARRAY_REF. Use build_java_arraystore_check. * check-init.c (check_init): Update to reflect that an array length access is now a COMPONENT_REF. * gcj.texi (Code Generation): Improve documentation of -fno-bounds-check. Add documentation for -fno-store-check. * java-tree.h (flag_store_check): Declare. (build_java_arraystore_check): Declare. * lang.c (flag_store_check): Initialize to 1. (lang_f_options): Add store-check option. * jvspec.c: Don't pass store-check option to jvgenmain. * lang-options.h: Add help string for -fno-store-check. From-SVN: r50129
Diffstat (limited to 'gcc/java/expr.c')
-rw-r--r--gcc/java/expr.c140
1 files changed, 89 insertions, 51 deletions
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index 0459310..80b2910 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -79,7 +79,6 @@ static void java_push_constant_from_pool PARAMS ((struct JCF *, int));
static void java_stack_pop PARAMS ((int));
static tree build_java_throw_out_of_bounds_exception PARAMS ((tree));
static tree build_java_check_indexed_type PARAMS ((tree, tree));
-static tree java_array_data_offset PARAMS ((tree));
static tree case_identity PARAMS ((tree, tree));
static unsigned char peek_opcode_at_pc PARAMS ((struct JCF *, int, int));
static bool emit_init_test_initialization PARAMS ((struct hash_entry *,
@@ -628,11 +627,6 @@ build_java_ret (location)
/* Implementation of operations on array: new, load, store, length */
-/* Array core info access macros */
-
-#define JAVA_ARRAY_LENGTH_OFFSET(A) \
- byte_position (TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (TREE_TYPE (A)))))
-
tree
decode_newarray_type (atype)
int atype;
@@ -699,6 +693,7 @@ build_java_array_length_access (node)
tree node;
{
tree type = TREE_TYPE (node);
+ tree array_type = TREE_TYPE (type);
HOST_WIDE_INT length;
if (!is_array_type_p (type))
@@ -707,13 +702,13 @@ build_java_array_length_access (node)
length = java_array_type_length (type);
if (length >= 0)
return build_int_2 (length, 0);
- node = build1 (INDIRECT_REF, int_type_node,
- fold (build (PLUS_EXPR, ptr_type_node,
- java_check_reference (node,
- flag_check_references),
- JAVA_ARRAY_LENGTH_OFFSET(node))));
+
+ node = build (COMPONENT_REF, int_type_node,
+ build_java_indirect_ref (array_type, node,
+ flag_check_references),
+ lookup_field (&array_type, get_identifier ("length")));
IS_ARRAY_LENGTH_ACCESS (node) = 1;
- return fold (node);
+ return node;
}
/* Optionally checks a reference against the NULL pointer. ARG1: the
@@ -752,19 +747,6 @@ build_java_indirect_ref (type, expr, check)
return build1 (INDIRECT_REF, type, java_check_reference (expr, check));
}
-static tree
-java_array_data_offset (array)
- tree array;
-{
- tree array_type = TREE_TYPE (TREE_TYPE (array));
- tree data_fld = TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (array_type)));
-
- if (data_fld == NULL_TREE)
- return size_in_bytes (array_type);
- else
- return byte_position (data_fld);
-}
-
/* Implement array indexing (either as l-value or r-value).
Returns a tree for ARRAY[INDEX], assume TYPE is the element type.
Optionally performs bounds checking and/or test to NULL.
@@ -774,12 +756,10 @@ tree
build_java_arrayaccess (array, type, index)
tree array, type, index;
{
- tree arith, node, throw = NULL_TREE;
-
- arith = fold (build (PLUS_EXPR, int_type_node,
- java_array_data_offset (array),
- fold (build (MULT_EXPR, int_type_node,
- index, size_in_bytes(type)))));
+ tree node, throw = NULL_TREE;
+ tree data_field;
+ tree ref;
+ tree array_type = TREE_TYPE (TREE_TYPE (array));
if (flag_bounds_check)
{
@@ -803,23 +783,86 @@ build_java_arrayaccess (array, type, index)
}
}
- /* The SAVE_EXPR is for correct evaluation order. It would be
- cleaner to use force_evaluation_order (see comment there), but
- that is difficult when we also have to deal with bounds
- checking. The SAVE_EXPR is not necessary to do that when we're
- not checking for array bounds. */
- if (TREE_SIDE_EFFECTS (index) && throw)
- throw = build (COMPOUND_EXPR, int_type_node, save_expr (array), throw);
-
- node = build1 (INDIRECT_REF, type,
- fold (build (PLUS_EXPR, ptr_type_node,
- java_check_reference (array,
- flag_check_references),
- (throw ? build (COMPOUND_EXPR, int_type_node,
- throw, arith ) : arith))));
+ /* If checking bounds, wrap the index expr with a COMPOUND_EXPR in order
+ to have the bounds check evaluated first. */
+ if (throw != NULL_TREE)
+ index = build (COMPOUND_EXPR, int_type_node, throw, index);
+
+ data_field = lookup_field (&array_type, get_identifier ("data"));
+
+ ref = build (COMPONENT_REF, TREE_TYPE (data_field),
+ build_java_indirect_ref (array_type, array,
+ flag_check_references),
+ data_field);
+
+ node = build (ARRAY_REF, type, ref, index);
return node;
}
+/* Generate code to throw an ArrayStoreException if OBJECT is not assignable
+ (at runtime) to an element of ARRAY. A NOP_EXPR is returned if it can
+ determine that no check is required. */
+
+tree
+build_java_arraystore_check (array, object)
+ tree array;
+ tree object;
+{
+ tree check, element_type;
+ tree array_type_p = TREE_TYPE (array);
+ tree object_type = TYPE_NAME (TREE_TYPE (TREE_TYPE (object)));
+
+ if (! is_array_type_p (array_type_p))
+ abort ();
+
+ /* Get the TYPE_DECL for ARRAY's element type. */
+ element_type = TYPE_NAME (TREE_TYPE (TREE_TYPE (TREE_TYPE (array_type_p))));
+
+ if (TREE_CODE (element_type) != TYPE_DECL
+ || TREE_CODE (object_type) != TYPE_DECL)
+ abort ();
+
+ if (!flag_store_check)
+ return build1 (NOP_EXPR, array_type_p, array);
+
+ /* No check is needed if the element type is final or is itself an array.
+ Also check that element_type matches object_type, since in the bytecode
+ compilation case element_type may be the actual element type of the arra
+ rather than its declared type. */
+ if (element_type == object_type
+ && (TYPE_ARRAY_P (TREE_TYPE (element_type))
+ || CLASS_FINAL (element_type)))
+ return build1 (NOP_EXPR, array_type_p, array);
+
+ /* Avoid the check if OBJECT was just loaded from the same array. */
+ if (TREE_CODE (object) == ARRAY_REF)
+ {
+ tree target;
+ tree source = TREE_OPERAND (object, 0); /* COMPONENT_REF. */
+ source = TREE_OPERAND (source, 0); /* INDIRECT_REF. */
+ source = TREE_OPERAND (source, 0); /* Source array's DECL or SAVE_EXPR. */
+ if (TREE_CODE (source) == SAVE_EXPR)
+ source = TREE_OPERAND (source, 0);
+
+ target = array;
+ if (TREE_CODE (target) == SAVE_EXPR)
+ target = TREE_OPERAND (target, 0);
+
+ if (source == target)
+ return build1 (NOP_EXPR, array_type_p, array);
+ }
+
+ /* Build an invocation of _Jv_CheckArrayStore */
+ check = build (CALL_EXPR, void_type_node,
+ build_address_of (soft_checkarraystore_node),
+ tree_cons (NULL_TREE, array,
+ build_tree_list (NULL_TREE, object)),
+ NULL_TREE);
+ TREE_SIDE_EFFECTS (check) = 1;
+
+ return check;
+}
+
/* Makes sure that INDEXED_TYPE is appropriate. If not, make it from
ARRAY_NODE. This function is used to retrieve something less vague than
a pointer type when indexing the first dimension of something like [[<t>.
@@ -973,12 +1016,7 @@ expand_java_arraystore (rhs_type_node)
if (TREE_CODE (rhs_type_node) == POINTER_TYPE)
{
- tree check = build (CALL_EXPR, void_type_node,
- build_address_of (soft_checkarraystore_node),
- tree_cons (NULL_TREE, array,
- build_tree_list (NULL_TREE, rhs_node)),
- NULL_TREE);
- TREE_SIDE_EFFECTS (check) = 1;
+ tree check = build_java_arraystore_check (array, rhs_node);
expand_expr_stmt (check);
}