Commit 4ff17c6a by Andrew Haley Committed by Andrew Haley

gcj.texi (Configure-time Options): Add -fcheck-references.

2001-02-07  Andrew Haley  <aph@redhat.com>

        * gcj.texi (Configure-time Options): Add -fcheck-references.
        * expr.c (build_java_indirect_ref): New function.
        (build_java_array_length_access): Use build_java_indirect_ref to
        check for null references.
        (build_java_arrayaccess): Likewise.
        (build_get_class): Likewise.
        (build_field_ref): Likewise.
        (invoke_build_dtable): Likewise.
        (build_invokeinterface): Likewise.
        * lang.c (lang_f_options): Add flag_check_references.
        * jvspec.c (jvgenmain_spec): Add flag_check_references.
        * java-tree.h (flag_check_references): New variable.
        * lang.c (flag_check_references): Likewise.

From-SVN: r40780
parent 8e4ce833
2001-02-07 Andrew Haley <aph@redhat.com>
* gcj.texi (Configure-time Options): Add -fcheck-references.
* expr.c (build_java_indirect_ref): New function.
(build_java_array_length_access): Use build_java_indirect_ref to
check for null references.
(build_java_arrayaccess): Likewise.
(build_get_class): Likewise.
(build_field_ref): Likewise.
(invoke_build_dtable): Likewise.
(build_invokeinterface): Likewise.
* lang.c (lang_f_options): Add flag_check_references.
* jvspec.c (jvgenmain_spec): Add flag_check_references.
* java-tree.h (flag_check_references): New variable.
* lang.c (flag_check_references): Likewise.
2001-03-23 Bryce McKinlay <bryce@albatross.co.nz> 2001-03-23 Bryce McKinlay <bryce@albatross.co.nz>
* gjavah.c (cxx_keywords): Update from the definitive list in cp/lex.c. * gjavah.c (cxx_keywords): Update from the definitive list in cp/lex.c.
......
...@@ -710,36 +710,46 @@ build_java_array_length_access (node) ...@@ -710,36 +710,46 @@ build_java_array_length_access (node)
length = java_array_type_length (type); length = java_array_type_length (type);
if (length >= 0) if (length >= 0)
return build_int_2 (length, 0); return build_int_2 (length, 0);
return fold (build1 (INDIRECT_REF, int_type_node,
return fold (build1 (INDIRECT_REF,
int_type_node,
fold (build (PLUS_EXPR, ptr_type_node, fold (build (PLUS_EXPR, ptr_type_node,
node, java_check_reference (node, 1),
JAVA_ARRAY_LENGTH_OFFSET(node))))); JAVA_ARRAY_LENGTH_OFFSET(node)))));
} }
/* Optionally checks an array against the NULL pointer, eventually throwing a /* Optionally checks a reference against the NULL pointer. ARG1: the
NullPointerException. It could replace signal handling, but tied to NULL. expr, ARG2: we should check the reference. Don't generate extra
ARG1: the pointer to check, ARG2: the expression to use if checks if we're not generating code. */
the pointer is non-null and ARG3 the type that should be returned. */
tree
java_check_reference (expr, check)
tree expr;
int check;
{
if (!flag_syntax_only && check)
{
tree cond;
expr = save_expr (expr);
cond = build (COND_EXPR, void_type_node,
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);
}
return expr;
}
/* Reference an object: just like an INDIRECT_REF, but with checking. */
tree tree
build_java_arraynull_check (node, expr, type) build_java_indirect_ref (type, expr, check)
tree node ATTRIBUTE_UNUSED; tree type;
tree expr; tree expr;
tree type ATTRIBUTE_UNUSED; int check;
{ {
#if 0 return build1 (INDIRECT_REF, type, java_check_reference (expr, check));
static int java_array_access_throws_null_exception = 0;
node = ???;
if (java_array_access_throws_null_exception)
return (build (COND_EXPR,
type,
build (EQ_EXPR, int_type_node, node, null_pointer_node),
build_java_athrow (node), expr ));
else
#endif
return (expr);
} }
static tree static tree
...@@ -792,15 +802,15 @@ build_java_arrayaccess (array, type, index) ...@@ -792,15 +802,15 @@ build_java_arrayaccess (array, type, index)
TREE_SIDE_EFFECTS( throw ) = 1; TREE_SIDE_EFFECTS( throw ) = 1;
} }
} }
node = build1 (INDIRECT_REF, type, node = build1 (INDIRECT_REF, type,
fold (build (PLUS_EXPR, ptr_type_node, fold (build (PLUS_EXPR, ptr_type_node,
array, java_check_reference (array, flag_check_references),
(throw ? build (COMPOUND_EXPR, int_type_node, (throw ? build (COMPOUND_EXPR, int_type_node,
throw, arith ) throw, arith )
: arith)))); : arith))));
return (fold (build_java_arraynull_check (array, node, type))); return node;
} }
/* Makes sure that INDEXED_TYPE is appropriate. If not, make it from /* Makes sure that INDEXED_TYPE is appropriate. If not, make it from
...@@ -1008,7 +1018,7 @@ expand_java_array_length () ...@@ -1008,7 +1018,7 @@ expand_java_array_length ()
tree array = pop_value (ptr_type_node); tree array = pop_value (ptr_type_node);
tree length = build_java_array_length_access (array); tree length = build_java_array_length_access (array);
push_value (build_java_arraynull_check (array, length, int_type_node)); push_value (length);
} }
/* Emit code for the call to _Jv_Monitor{Enter,Exit}. CALL can be /* Emit code for the call to _Jv_Monitor{Enter,Exit}. CALL can be
...@@ -1118,7 +1128,8 @@ build_get_class (value) ...@@ -1118,7 +1128,8 @@ build_get_class (value)
return build (COMPONENT_REF, class_ptr_type, return build (COMPONENT_REF, class_ptr_type,
build1 (INDIRECT_REF, dtable_type, build1 (INDIRECT_REF, dtable_type,
build (COMPONENT_REF, dtable_ptr_type, build (COMPONENT_REF, dtable_ptr_type,
build1 (INDIRECT_REF, object_type_node, value), build_java_indirect_ref (object_type_node, value,
flag_check_references),
vtable_field)), vtable_field)),
class_field); class_field);
} }
...@@ -1485,8 +1496,8 @@ build_field_ref (self_value, self_class, name) ...@@ -1485,8 +1496,8 @@ build_field_ref (self_value, self_class, name)
#ifdef JAVA_USE_HANDLES #ifdef JAVA_USE_HANDLES
self_value = unhand_expr (self_value); self_value = unhand_expr (self_value);
#endif #endif
self_value = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (self_value)), self_value = build_java_indirect_ref (TREE_TYPE (TREE_TYPE (self_value)),
self_value); self_value, flag_check_references);
return fold (build (COMPONENT_REF, TREE_TYPE (field_decl), return fold (build (COMPONENT_REF, TREE_TYPE (field_decl),
self_value, field_decl)); self_value, field_decl));
} }
...@@ -1780,7 +1791,8 @@ invoke_build_dtable (is_invoke_interface, arg_list) ...@@ -1780,7 +1791,8 @@ invoke_build_dtable (is_invoke_interface, arg_list)
if (dtable_ident == NULL_TREE) if (dtable_ident == NULL_TREE)
dtable_ident = get_identifier ("vtable"); dtable_ident = get_identifier ("vtable");
dtable = build1 (INDIRECT_REF, object_type_node, objectref ); dtable = build_java_indirect_ref (object_type_node, objectref,
flag_check_references);
dtable = build (COMPONENT_REF, dtable_ptr_type, dtable, dtable = build (COMPONENT_REF, dtable_ptr_type, dtable,
lookup_field (&object_type_node, dtable_ident)); lookup_field (&object_type_node, dtable_ident));
...@@ -1829,7 +1841,7 @@ build_invokeinterface (dtable, method) ...@@ -1829,7 +1841,7 @@ build_invokeinterface (dtable, method)
ggc_add_tree_root (&class_ident, 1); ggc_add_tree_root (&class_ident, 1);
} }
dtable = build1 (INDIRECT_REF, dtable_type, dtable); dtable = build_java_indirect_ref (dtable_type, dtable, flag_check_references);
dtable = build (COMPONENT_REF, class_ptr_type, dtable, dtable = build (COMPONENT_REF, class_ptr_type, dtable,
lookup_field (&dtable_type, class_ident)); lookup_field (&dtable_type, class_ident));
...@@ -1875,7 +1887,7 @@ expand_invoke (opcode, method_ref_index, nargs) ...@@ -1875,7 +1887,7 @@ expand_invoke (opcode, method_ref_index, nargs)
const char *self_name const char *self_name
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type))); = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
tree call, func, method, arg_list, method_type; tree call, func, method, arg_list, method_type;
tree cond = NULL_TREE; tree check = NULL_TREE;
if (! CLASS_LOADED_P (self_type)) if (! CLASS_LOADED_P (self_type))
{ {
...@@ -1957,7 +1969,7 @@ expand_invoke (opcode, method_ref_index, nargs) ...@@ -1957,7 +1969,7 @@ expand_invoke (opcode, method_ref_index, nargs)
the new `self' expression once. */ the new `self' expression once. */
tree save_arg = save_expr (TREE_VALUE (arg_list)); tree save_arg = save_expr (TREE_VALUE (arg_list));
TREE_VALUE (arg_list) = save_arg; TREE_VALUE (arg_list) = save_arg;
cond = build (EQ_EXPR, boolean_type_node, save_arg, null_pointer_node); check = java_check_reference (save_arg, 1);
func = build_known_method_ref (method, method_type, self_type, func = build_known_method_ref (method, method_type, self_type,
method_signature, arg_list); method_signature, arg_list);
} }
...@@ -1974,20 +1986,9 @@ expand_invoke (opcode, method_ref_index, nargs) ...@@ -1974,20 +1986,9 @@ expand_invoke (opcode, method_ref_index, nargs)
call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE); call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE);
TREE_SIDE_EFFECTS (call) = 1; TREE_SIDE_EFFECTS (call) = 1;
if (cond != NULL_TREE) if (check != NULL_TREE)
{ {
/* We have to make the `then' branch a compound expression to call = build (COMPOUND_EXPR, TREE_TYPE (call), check, call);
make the types turn out right. This seems bizarre. */
call = build (COND_EXPR, TREE_TYPE (call), cond,
build (COMPOUND_EXPR, TREE_TYPE (call),
build (CALL_EXPR, void_type_node,
build_address_of (soft_nullpointer_node),
NULL_TREE, NULL_TREE),
(FLOAT_TYPE_P (TREE_TYPE (call))
? build_real (TREE_TYPE (call), dconst0)
: build1 (CONVERT_EXPR, TREE_TYPE (call),
integer_zero_node))),
call);
TREE_SIDE_EFFECTS (call) = 1; TREE_SIDE_EFFECTS (call) = 1;
} }
...@@ -2428,8 +2429,9 @@ java_lang_expand_expr (exp, target, tmode, modifier) ...@@ -2428,8 +2429,9 @@ java_lang_expand_expr (exp, target, tmode, modifier)
init = init_decl; init = init_decl;
} }
expand_assignment (build (COMPONENT_REF, TREE_TYPE (data_fld), expand_assignment (build (COMPONENT_REF, TREE_TYPE (data_fld),
build1 (INDIRECT_REF, array_type, build_java_indirect_ref (array_type,
array_decl), data_fld), init, 0, 0); array_decl, flag_check_references),
data_fld), init, 0, 0);
return tmp; return tmp;
} }
case BLOCK: case BLOCK:
......
...@@ -758,6 +758,12 @@ hash table and not in the object itself. ...@@ -758,6 +758,12 @@ hash table and not in the object itself.
On some systems, a library routine is called to perform integer On some systems, a library routine is called to perform integer
division. This is required to get exception handling correct when division. This is required to get exception handling correct when
dividing by zero. dividing by zero.
@item -fcheck-references
On some systems it's necessary to insert inline checks whenever
accessing an object via a reference. On other systems you won't need
this because null pointer accesses are caught automatically by the
processor.
@end table @end table
......
...@@ -181,6 +181,9 @@ extern int flag_use_boehm_gc; ...@@ -181,6 +181,9 @@ extern int flag_use_boehm_gc;
object to its synchronization structure. */ object to its synchronization structure. */
extern int flag_hash_synchronization; extern int flag_hash_synchronization;
/* When non zero, generate checks for references to NULL. */
extern int flag_check_references;
/* Encoding used for source files. */ /* Encoding used for source files. */
extern const char *current_encoding; extern const char *current_encoding;
...@@ -1010,6 +1013,8 @@ extern tree build_anewarray PARAMS ((tree, tree)); ...@@ -1010,6 +1013,8 @@ extern tree build_anewarray PARAMS ((tree, tree));
extern tree build_new_array PARAMS ((tree, tree)); extern tree build_new_array PARAMS ((tree, tree));
extern tree build_java_array_length_access PARAMS ((tree)); extern tree build_java_array_length_access PARAMS ((tree));
extern tree build_java_arraynull_check PARAMS ((tree, tree, tree)); extern tree build_java_arraynull_check PARAMS ((tree, tree, tree));
extern tree build_java_indirect_ref PARAMS ((tree, tree, int));
extern tree java_check_reference PARAMS ((tree, int));
extern tree build_get_class PARAMS ((tree)); extern tree build_get_class PARAMS ((tree));
extern tree build_instanceof PARAMS ((tree, tree)); extern tree build_instanceof PARAMS ((tree, tree));
extern tree create_label_decl PARAMS ((tree)); extern tree create_label_decl PARAMS ((tree));
......
...@@ -63,6 +63,7 @@ const char jvgenmain_spec[] = ...@@ -63,6 +63,7 @@ const char jvgenmain_spec[] =
%{<fuse-boehm-gc} %{<fhash-synchronization} %{<fjni}\ %{<fuse-boehm-gc} %{<fhash-synchronization} %{<fjni}\
%{<fclasspath*} %{<fCLASSPATH*} %{<foutput-class-dir}\ %{<fclasspath*} %{<fCLASSPATH*} %{<foutput-class-dir}\
%{<fuse-divide-subroutine} %{<fno-use-divide-subroutine}\ %{<fuse-divide-subroutine} %{<fno-use-divide-subroutine}\
%{<fcheck-references} %{<fno-check-references}\
%{f*} -fdollars-in-identifiers\ %{f*} -fdollars-in-identifiers\
%{aux-info*}\ %{aux-info*}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
......
...@@ -138,6 +138,9 @@ int flag_jni = 0; ...@@ -138,6 +138,9 @@ int flag_jni = 0;
file. */ file. */
int flag_newer = 1; int flag_newer = 1;
/* When non zero, generate checks for references to NULL. */
int flag_check_references = 0;
/* The encoding of the source file. */ /* The encoding of the source file. */
const char *current_encoding = NULL; const char *current_encoding = NULL;
...@@ -164,7 +167,8 @@ lang_f_options[] = ...@@ -164,7 +167,8 @@ lang_f_options[] =
{"use-divide-subroutine", &flag_use_divide_subroutine, 1}, {"use-divide-subroutine", &flag_use_divide_subroutine, 1},
{"use-boehm-gc", &flag_use_boehm_gc, 1}, {"use-boehm-gc", &flag_use_boehm_gc, 1},
{"hash-synchronization", &flag_hash_synchronization, 1}, {"hash-synchronization", &flag_hash_synchronization, 1},
{"jni", &flag_jni, 1} {"jni", &flag_jni, 1},
{"check-references", &flag_check_references, 1},
}; };
static struct string_option static struct string_option
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment