aboutsummaryrefslogtreecommitdiff
path: root/gcc/java
diff options
context:
space:
mode:
authorAndrew Haley <aph@cygnus.com>1999-07-21 14:28:33 +0000
committerAndrew Haley <aph@gcc.gnu.org>1999-07-21 14:28:33 +0000
commitaa4759c11cc78443455b69fca236c24ff89c91a1 (patch)
tree7a86e6410656ef434107be5353da306f7adf35c0 /gcc/java
parent9c1ce4332e0bfc9289296fde205af0eb3a21e50b (diff)
downloadgcc-aa4759c11cc78443455b69fca236c24ff89c91a1.zip
gcc-aa4759c11cc78443455b69fca236c24ff89c91a1.tar.gz
gcc-aa4759c11cc78443455b69fca236c24ff89c91a1.tar.bz2
lang.c (flag_use_divide_subroutine): New variable.
1999-07-15 Andrew Haley <aph@cygnus.com> * lang.c (flag_use_divide_subroutine): New variable. * typeck.c: (convert_ieee_real_to_integer): Bounds check fp-to-integer conversion. (convert): Call convert_ieee_real_to_integer when flag_fast_math is not set. * expr.c (build_java_soft_divmod): New function. (build_java_binop): Call build_java_soft_divmod if flag_use_divide_subroutine is set. * decl.c: soft_idiv_node, soft_irem_node, soft_ldiv_node, tree soft_lrem_node: new builtin functions. (init_decl_processing) Initialize the new builtins. * java-tree.h soft_idiv_node, soft_irem_node, soft_ldiv_node, tree soft_lrem_node: new builtin functions. (build_java_soft_divmod): New function. * parse.y: Call build_java_soft_divmod if flag_use_divide_subroutine is set. From-SVN: r28208
Diffstat (limited to 'gcc/java')
-rw-r--r--gcc/java/ChangeLog20
-rw-r--r--gcc/java/decl.c25
-rw-r--r--gcc/java/expr.c60
-rw-r--r--gcc/java/java-tree.h8
-rw-r--r--gcc/java/lang.c4
-rw-r--r--gcc/java/parse.y6
-rw-r--r--gcc/java/typeck.c49
7 files changed, 153 insertions, 19 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 2e7bb3a..372d29441 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,23 @@
+1999-07-15 Andrew Haley <aph@cygnus.com>
+
+ * lang.c (flag_use_divide_subroutine): New variable.
+ * typeck.c: (convert_ieee_real_to_integer): Bounds check
+ fp-to-integer conversion.
+ (convert): Call convert_ieee_real_to_integer when flag_fast_math
+ is not set.
+
+ * expr.c (build_java_soft_divmod): New function.
+ (build_java_binop): Call build_java_soft_divmod if
+ flag_use_divide_subroutine is set.
+ * decl.c: soft_idiv_node, soft_irem_node, soft_ldiv_node, tree
+ soft_lrem_node: new builtin functions.
+ (init_decl_processing) Initialize the new builtins.
+ * java-tree.h soft_idiv_node, soft_irem_node, soft_ldiv_node, tree
+ soft_lrem_node: new builtin functions.
+ (build_java_soft_divmod): New function.
+ * parse.y: Call build_java_soft_divmod if
+ flag_use_divide_subroutine is set.
+
Tue Jul 20 13:20:05 1999 Alexandre Petit-Bianco <apbianco@cygnus.com>
* parse.y (resolve_and_layout): Check methods only once.
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index de03e5fd..6779747 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -365,6 +365,11 @@ tree soft_monitorexit_node;
tree soft_lookupinterfacemethod_node;
tree soft_fmod_node;
tree soft_exceptioninfo_call_node;
+tree soft_idiv_node;
+tree soft_irem_node;
+tree soft_ldiv_node;
+tree soft_lrem_node;
+
/* Build (and pushdecl) a "promoted type" for all standard
types shorter than int. */
@@ -812,6 +817,26 @@ init_decl_processing ()
BUILT_IN_FMOD, "fmodf");
#endif
+ soft_idiv_node
+ = builtin_function ("_Jv_divI",
+ build_function_type (int_type_node, t),
+ NOT_BUILT_IN, NULL_PTR);
+
+ soft_irem_node
+ = builtin_function ("_Jv_remI",
+ build_function_type (int_type_node, t),
+ NOT_BUILT_IN, NULL_PTR);
+
+ soft_ldiv_node
+ = builtin_function ("_Jv_divJ",
+ build_function_type (long_type_node, t),
+ NOT_BUILT_IN, NULL_PTR);
+
+ soft_lrem_node
+ = builtin_function ("_Jv_remJ",
+ build_function_type (long_type_node, t),
+ NOT_BUILT_IN, NULL_PTR);
+
init_class_processing ();
}
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index d47ed1a..dbf6db5 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -1052,6 +1052,53 @@ expand_iinc (local_var_index, ival, pc)
expand_assignment (local_var, res, 0, 0);
}
+
+tree
+build_java_soft_divmod (op, type, op1, op2)
+ enum tree_code op;
+ tree type, op1, op2;
+{
+ tree call = NULL;
+ tree arg1 = convert (type, op1);
+ tree arg2 = convert (type, op2);
+
+ if (type == int_type_node)
+ {
+ switch (op)
+ {
+ case TRUNC_DIV_EXPR:
+ call = soft_idiv_node;
+ break;
+ case TRUNC_MOD_EXPR:
+ call = soft_irem_node;
+ break;
+ }
+ }
+ else if (type == long_type_node)
+ {
+ switch (op)
+ {
+ case TRUNC_DIV_EXPR:
+ call = soft_ldiv_node;
+ break;
+ case TRUNC_MOD_EXPR:
+ call = soft_lrem_node;
+ break;
+ }
+ }
+
+ if (! call)
+ fatal ("Internal compiler error in build_java_soft_divmod");
+
+ call = build (CALL_EXPR, type,
+ build_address_of (call),
+ tree_cons (NULL_TREE, arg1,
+ build_tree_list (NULL_TREE, arg2)),
+ NULL_TREE);
+
+ return call;
+}
+
tree
build_java_binop (op, type, arg1, arg2)
enum tree_code op;
@@ -1100,10 +1147,11 @@ build_java_binop (op, type, arg1, arg2)
integer_zero_node));
return fold (build (COND_EXPR, int_type_node,
ifexp1, integer_negative_one_node, second_compare));
- }
-
+ }
+ case TRUNC_DIV_EXPR:
case TRUNC_MOD_EXPR:
- if (TREE_CODE (type) == REAL_TYPE)
+ if (TREE_CODE (type) == REAL_TYPE
+ && op == TRUNC_MOD_EXPR)
{
tree call;
if (type != double_type_node)
@@ -1120,6 +1168,12 @@ build_java_binop (op, type, arg1, arg2)
call = convert (type, call);
return call;
}
+
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && flag_use_divide_subroutine
+ && ! flag_syntax_only)
+ return build_java_soft_divmod (op, type, arg1, arg2);
+
break;
default: ;
}
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index be1f143..307218c 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -141,6 +141,9 @@ extern int flag_redundant;
extern int flag_not_overriding;
extern int flag_static_local_jdk1_1;
+/* When non zero, call a library routine to do integer divisions. */
+extern int flag_use_divide_subroutine;
+
/* The Java .class file that provides main_class; the main input file. */
extern struct JCF *current_jcf;
@@ -283,6 +286,10 @@ extern tree soft_monitorexit_node;
extern tree soft_lookupinterfacemethod_node;
extern tree soft_fmod_node;
extern tree soft_exceptioninfo_call_node;
+extern tree soft_idiv_node;
+extern tree soft_irem_node;
+extern tree soft_ldiv_node;
+extern tree soft_lrem_node;
extern tree access_flags_type_node;
@@ -544,6 +551,7 @@ extern tree invoke_build_dtable PROTO ((int, tree));
extern tree build_field_ref PROTO ((tree, tree, tree));
extern void pushdecl_force_head PROTO ((tree));
extern tree build_java_binop PROTO ((enum tree_code, tree, tree, tree));
+extern tree build_java_soft_divmod PROTO ((enum tree_code, tree, tree, tree));
extern tree binary_numeric_promotion PROTO ((tree, tree, tree *, tree *));
extern tree build_java_arrayaccess PROTO ((tree, tree, tree));
extern tree build_newarray PROTO ((int, tree));
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index cd6fb3b..976ed64 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -105,6 +105,9 @@ int flag_not_overriding = 0;
/* When non zero, warns that final local are treated as non final. */
int flag_static_local_jdk1_1 = 0;
+/* When non zero, call a library routine to do integer divisions. */
+int flag_use_divide_subroutine = 1;
+
/* From gcc/flags.h, and indicates if exceptions are turned on or not. */
extern int flag_new_exceptions;
@@ -123,6 +126,7 @@ lang_f_options[] =
{"assume-compiled", &flag_assume_compiled, 1},
{"emit-class-file", &flag_emit_class_files, 1},
{"emit-class-files", &flag_emit_class_files, 1},
+ {"use-divide-subroutine", &flag_use_divide_subroutine, 1},
};
JCF *current_jcf;
diff --git a/gcc/java/parse.y b/gcc/java/parse.y
index be1c788..23b2c7a 100644
--- a/gcc/java/parse.y
+++ b/gcc/java/parse.y
@@ -9411,6 +9411,12 @@ patch_binop (node, wfl_op1, wfl_op2)
if (code == RDIV_EXPR && TREE_CODE (prom_type) == INTEGER_TYPE)
TREE_SET_CODE (node, TRUNC_DIV_EXPR);
+ if (TREE_CODE (prom_type) == INTEGER_TYPE
+ && flag_use_divide_subroutine
+ && ! flag_emit_class_files
+ && (code == RDIV_EXPR || code == TRUNC_MOD_EXPR))
+ return build_java_soft_divmod (TREE_CODE (node), prom_type, op1, op2);
+
/* This one is more complicated. FLOATs are processed by a
function call to soft_fmod. Duplicate the value of the
COMPOUND_ASSIGN_P flag. */
diff --git a/gcc/java/typeck.c b/gcc/java/typeck.c
index 1416245..99536ff 100644
--- a/gcc/java/typeck.c
+++ b/gcc/java/typeck.c
@@ -55,23 +55,43 @@ set_local_type (slot, type)
/* Convert an IEEE real to an integer type. The result of such a
conversion when the source operand is a NaN isn't defined by
- IEEE754, but by the Java language standard: it must be zero. This
- conversion produces something like:
-
- ({ double tmp = expr; (tmp != tmp) ? 0 : (int)tmp; })
-
- */
+ IEEE754, but by the Java language standard: it must be zero. Also,
+ overflows must be clipped to within range. This conversion
+ produces something like:
+
+ ((expr >= (float)MAX_INT)
+ ? MAX_INT
+ : ((expr <= (float)MIN_INT)
+ ? MIN_INT
+ : ((expr != expr)
+ ? 0
+ : (int)expr))) */
static tree
convert_ieee_real_to_integer (type, expr)
tree type, expr;
{
+ tree result;
expr = save_expr (expr);
- return build (COND_EXPR, type,
- build (NE_EXPR, boolean_type_node, expr, expr),
- convert (type, integer_zero_node),
- convert_to_integer (type, expr));
+ result = build (COND_EXPR, type,
+ build (NE_EXPR, boolean_type_node, expr, expr),
+ convert (type, integer_zero_node),
+ convert_to_integer (type, expr));
+
+ result = build (COND_EXPR, type,
+ build (LE_EXPR, boolean_type_node, expr,
+ convert (TREE_TYPE (expr), TYPE_MIN_VALUE (type))),
+ TYPE_MIN_VALUE (type),
+ result);
+
+ result = build (COND_EXPR, type,
+ build (GE_EXPR, boolean_type_node, expr,
+ convert (TREE_TYPE (expr), TYPE_MAX_VALUE (type))),
+ TYPE_MAX_VALUE (type),
+ result);
+
+ return result;
}
/* Create an expression whose value is that of EXPR,
@@ -100,12 +120,9 @@ convert (type, expr)
return fold (convert_to_boolean (type, expr));
if (code == INTEGER_TYPE)
{
- if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
-#ifdef TARGET_SOFT_FLOAT
- && !TARGET_SOFT_FLOAT
-#endif
- && !flag_emit_class_files
- && !flag_fast_math
+ if (! flag_fast_math
+ && ! flag_emit_class_files
+ && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
&& TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
return fold (convert_ieee_real_to_integer (type, expr));
else