diff options
author | Diego Novillo <dnovillo@gcc.gnu.org> | 2004-05-13 02:41:07 -0400 |
---|---|---|
committer | Diego Novillo <dnovillo@gcc.gnu.org> | 2004-05-13 02:41:07 -0400 |
commit | 6de9cd9a886ea695aa892c3c7c07818a7b7e9e6f (patch) | |
tree | a2568888a519c077427b133de9ece5879a8484a5 /gcc/java | |
parent | ac1a20aec53364d77f3bdff94a2a0a06840e0fe9 (diff) | |
download | gcc-6de9cd9a886ea695aa892c3c7c07818a7b7e9e6f.zip gcc-6de9cd9a886ea695aa892c3c7c07818a7b7e9e6f.tar.gz gcc-6de9cd9a886ea695aa892c3c7c07818a7b7e9e6f.tar.bz2 |
Merge tree-ssa-20020619-branch into mainline.
From-SVN: r81764
Diffstat (limited to 'gcc/java')
-rw-r--r-- | gcc/java/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/java/ChangeLog.tree-ssa | 360 | ||||
-rw-r--r-- | gcc/java/Make-lang.in | 5 | ||||
-rw-r--r-- | gcc/java/builtins.c | 2 | ||||
-rw-r--r-- | gcc/java/check-init.c | 4 | ||||
-rw-r--r-- | gcc/java/class.c | 42 | ||||
-rw-r--r-- | gcc/java/constants.c | 42 | ||||
-rw-r--r-- | gcc/java/decl.c | 448 | ||||
-rw-r--r-- | gcc/java/except.c | 75 | ||||
-rw-r--r-- | gcc/java/expr.c | 334 | ||||
-rw-r--r-- | gcc/java/java-except.h | 3 | ||||
-rw-r--r-- | gcc/java/java-gimplify.c | 277 | ||||
-rw-r--r-- | gcc/java/java-tree.def | 9 | ||||
-rw-r--r-- | gcc/java/java-tree.h | 36 | ||||
-rw-r--r-- | gcc/java/jcf-parse.c | 15 | ||||
-rw-r--r-- | gcc/java/jcf-write.c | 4 | ||||
-rw-r--r-- | gcc/java/lang.c | 152 | ||||
-rw-r--r-- | gcc/java/lang.opt | 3 | ||||
-rw-r--r-- | gcc/java/parse.y | 191 | ||||
-rw-r--r-- | gcc/java/resource.c | 1 |
20 files changed, 1335 insertions, 679 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 25594a3..7ac2ba5 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,14 @@ +2004-05-13 Diego Novillo <dnovillo@redhat.com> + + Merge from tree-ssa-20020619-branch. See + ChangeLog.tree-ssa for details. + + * Make-lang.in, builtins.c, check-init.c, class.c, + constants.c, decl.c, except.c, expr.c, java-except.h, + java-tree.def, java-tree.h, jcf-parse.c, jcf-write.c, + lang.c, lang.opt, parse.y, resource.c: Merged. + * java-gimplify.c: New file. + 2004-05-10 Andrew Haley <aph@redhat.com> * parse.y (create_class): Set TYPE_VFIELD. diff --git a/gcc/java/ChangeLog.tree-ssa b/gcc/java/ChangeLog.tree-ssa new file mode 100644 index 0000000..81081a5 --- /dev/null +++ b/gcc/java/ChangeLog.tree-ssa @@ -0,0 +1,360 @@ +2004-05-10 Andrew Haley <aph@redhat.com> + + * java-gimplify.c (java_gimplify_expr): Copy the LHS of a binary + expression into a temporary variable. + + (java_gimplify_new_array_init): Set the DECL_CONTEXT of array and + tmp to current_function_decl. + +2004-04-13 Diego Novillo <dnovillo@redhat.com> + + * expr.c (build_expr_wfl): Don't check type nodes for + side effects. + +2004-04-12 Diego Novillo <dnovillo@redhat.com> + + * decl.c (java_expand_stmt): Remove. + * lang.c (LANG_HOOKS_RTL_EXPAND_STMT): Remove. + +2004-02-24 Richard Henderson <rth@redhat.com> + + * java-gimplify.c (java_gimplify_new_array_init): Remove extra + argument building BLOCK. + +2004-02-19 Steven Bosscher <stevenb@suse.de> + + * decl.c (poplevel): Don't output nested inline functions. + +2004-02-16 Richard Henderson <rth@redhat.com> + + * builtins.c (java_build_function_call_expr): Add static chain + operand to call_expr. + +2004-01-29 Richard Henderson <rth@redhat.com> + + PR java/12906 + * decl.c (maybe_pushlevels): Careful with TREE_CHAIN when + registering decls with push_jvm_slot. + +2003-12-10 Diego Novillo <dnovillo@redhat.com> + + * parse.y (resolve_field_access): Remove superfluous + initialization of decl. + +2003-12-10 Richard Henderson <rth@redhat.com> + + * lang.c (java_post_options): Don't ever use rtl inlining. + +2003-12-06 Jan Hubicka <jh@suse.cz> + + * parse.y (resolve_field_access): Initialize decl. + +2003-11-31 Richard Henderson <rth@redhat.com> + + * lang.c (java_start_inlining): Remove. + (LANG_HOOKS_TREE_INLINING_START_INLINING): Remove. + +2003-11-31 Richard Henderson <rth@redhat.com> + + * jcf-parse.c (java_parse_file): Finalize cgraph after emitting + class tables. + +2003-11-24 Richard Henderson <rth@redhat.com> + + * Make-lang.in (parse.o): Remove -Wno-error. + +2003-11-20 Richard Henderson <rth@redhat.com> + + * constants.c (build_constant_data_ref): Lay out the array type. + +2003-11-20 Richard Henderson <rth@redhat.com> + + * class.c (build_indirect_class_ref): Use convert. + * constants.c (build_constant_data_ref): Fix type on the decl + and return that directly. + (build_constants_constructor): Remove kruft to match. + (build_ref_from_constant_pool): Use ARRAY_REF. + * expr.c (build_java_indirect_ref): Use convert. + (build_known_method_ref): Likewise. + * parse.y (patch_string_cst): Likewise. + + * class.c (finish_class): Kill code to output_inline_function. + +2003-11-12 Jason Merrill <jason@redhat.com> + + PR optimization/12547 + * lang.c (java_tree_inlining_walk_subtrees): Restore. + (LANG_HOOKS_TREE_INLINING_WALK_SUBTREES): Restore. + +2003-11-12 Richard Henderson <rth@redhat.com> + + * java-gimplify.c (java_gimplify_expr): Use annotate_with_locus + instead of annotate_all_with_locus. + +2003-11-10 Richard Henderson <rth@redhat.com> + + * expr.c: Use append_to_statement_list instead of add_tree. + +2003-10-30 Richard Henderson <rth@redhat.com> + + * java-gimplify.c (cleanup_compound_expr): Remove. + (cleanup_try_finally_expr): Remove. + (java_gimplify_expr): Don't call them. + (java_gimplify_case_expr): Use create_artificial_label. + (java_gimplify_default_expr): Likewise. + +2003-10-30 Richard Henderson <rth@redhat.com> + + * expr.c (expand_java_switch, expand_java_add_case): New. + (LOOKUP_SWITCH, TABLE_SWITCH): Use them. + +2003-10-23 Richard Henderson <rth@redhat.com> + + * java-gimplify.c (java_gimplify_expr): Return gimplify_status. + +2003-10-14 Richard Henderson <rth@redhat.com> + + * decl.c (finish_method): Set cfun->function_end_locus. + * java-gimplify.c (java_gimplify_expr): Set input_location + for EXPR_WITH_FILE_LOCATION. Use annotate_all_with_locus. + * parse.h (DECL_SOURCE_LINE_MERGE): Remove. + (DECL_SOURCE_LINE_FIRST, DECL_SOURCE_LINE_LAST): Remove. + * parse.y (missing_return_error): Use DECL_FUNCTION_LAST_LINE. + (finish_method_declaration): Likewise. + (start_artificial_method_body): Likewise. + (lookup_cl): Use DECL_SOURCE_LINE. + (start_complete_expand_method): Likewise. + (java_complete_lhs): Fix IS_EXPR_CODE_CLASS check. + +2003-10-13 Richard Henderson <rth@redhat.com> + + * decl.c (java_add_stmt): Use annotate_with_locus. + +2003-10-13 Richard Henderson <rth@redhat.com> + + * expr.c (build_java_jsr): Don't emit LABEL_EXPR or + load_type_state here. + +2003-10-12 Richard Henderson <rth@redhat.com> + + * class.c (build_utf8_ref, get_dispatch_table): Set TREE_INVARIANT. + (make_class_data, build_symbol_entry, emit_symbol_table): Likewise. + * decl.c (java_init_decl_processing): Likewise. + * except.c (prepare_eh_table_type): Likewise. + * parse.y (patch_assignment, patch_binop): Likewise. + (patch_string_cst, patch_new_array_init): Likewise. + * resource.c (compile_resource_data): Likewise. + +2003-10-08 Jeff Sturm <jsturm@one-point.com> + + * decl.c (cgraph.h): Include. + (tree-inline.h, tree-dump.h, tree-flow.h): Remove includes. + (complete_start_java_method): Remove. + (start_java_method): Combine with complete_start_java_method. + Remove dead code. + (end_java_method): Don't patch or expand tree. + Use finish_method. + (finish_method): New function. + (java_expand_body): Use tree_rest_of_compilation. + (java_expand_stmt): New function. + + * java-gimplify.c (tree-dump.h): Include. + (java_genericize): New function. + (dump_java_tree): Declare. New function. + + * java-tree.h (start_complete_expand_method): Remove declaration. + (complete_start_java_method): Remove declaration. + (finish_method, java_expand_stmt, java_genericize): Declare. + + * lang.c (LANG_HOOKS_RTL_EXPAND_STMT): Define. + + * parse.y (tree-inline.h, tree-dump.h, tree-flow.h, + cgraph.h): Remove includes. + (start_complete_expand_method): Declare. + (source_end_java_method): Don't expand tree. Use finish_method. + Reset current_function_decl. + (java_expand_method_bodies): Don't patch tree for class + initialization or method synchronization. + +2003-10-01 Richard Henderson <rth@redhat.com> + + * decl.c (end_java_method): Invoke remove_useless_stmts_and_vars + and lower_eh_constructs. + * parse.y (source_end_java_method): Likewise. + +2003-09-24 Jason Merrill <jason@redhat.com> + + * decl.c, jcf-parse.c, jcf-write.c, parse.h, parse.y, resource.c: + Revert from TREE_LOCUS to DECL_SOURCE_LOCATION. + +2003-09-18 Richard Henderson <rth@redhat.com> + + * lang.c (java_estimate_num_insns): Take an expr, not a decl. + +2003-08-12 Diego Novillo <dnovillo@redhat.com> + + * java-gimplify.c (java_gimplify_block): If the body is a + NULL_TREE, return an empty statement. + +2003-08-08 Jason Merrill <jason@redhat.com> + + * parse.y (source_end_java_method): Support + !keep_function_tree_in_gimple_form. + Do TDI_generic dump. + +2003-07-31 Andrew Haley <aph@redhat.com> + + * java-tree.h: (add_stmt_to_compound): New function. + (java_add_stmt): New function. + (java_add_local_var): New function. + (get_stmts): New function. + * java-gimplify.c (java_gimplify_block): Allow for null body. + * except.c (link_handler): Set h->stmt. + (expand_start_java_handler): Build a TRY_CATCH_EXPR for this + range; don't expand_eh_region_start. + (expand_end_java_handler): Rewrite. + * java-except.h (stmt): New field. + * expr.c (flush_quick_stack): Replace expand_assignment with + java_add_stmt. + (java_stack_dup): Replace emit_move_insn with java_add_stmt. + (build_java_athrow): Replace expand_expr_stmt with java_add_stmt. + (build_java_jsr): Replace emit_jump with java_add_stmt (build (GOTO_EXPR)) + (build_java_ret): Replace expand_computed_goto with + java_add_stmt (build (GOTO_EXPR)) + (expand_java_arraystore): Replace expand_assignment with + java_add_stmt. + (expand_java_return): Replace expand_return with + java_add_stmt (build (RETURN_EXPR)) + (expand_load_internal): Remove layout_decl, DECL_REGISTER, + expand_decl, and expand_decl_init. Instead, add the local + variable and a MODIFY_EXPR to the current tree. + (expand_iinc): Replace expand_assignment with + java_add_stmt. + (expand_compare): Replace expand_cond with + java_add_stmt(build (COND_EXPR)) + (expand_java_goto): Replace expand_goto with + java_add_stmt (build (GOTO_EXPR)) + (expand_invoke): Replace expand_expr_stmt with java_add_stmt. + (build_jni_stub): Generate a BIND_EXPR to hold the block we've + created. Don't distinguish between source and byte compiler. + (expand_java_field_op): Replace expand_assignment with + java_add_stmt. + (java_expand_expr): Abort. No-one should call this function any + more. + (expand_byte_code): Replace expand_label with + java_add_stmt (build (LABEL_EXPR)) + (process_jvm_instruction): Replace build (JAVA_EXC_OBJ_EXPR) with + build_exception_object_ref. Replace expand_assignment with + java_add_stmt. + * except.c (link_handler): Null stmt field. + (expand_start_java_handler): Don't expand_eh_region_start. + Instead, generate a TRY_CATCH_EXPR and insert it into the tree + we're building. + (expand_end_java_handler): Don't expand_start_all_catch. Instead, + build a TRY_FINALLY_EXPR and wrap the catch block with it. + Don't expand_end_all_catch. + * decl.c (push_jvm_slot): Call pushdecl(). + (find_local_variable): Give symbolic names to unnamed local + variables. + (struct binding_level: stmts): New field. + (poplevel): If any statements have been generated at this level, + create a BIND_EXPR to hold them and copy the variables to it. If + we are at the outermost level, save this BIND_EXPR in the + DECL_SAVED_TREE of this function. + (maybe_pushlevels): Don't expand_start_bindings. + (maybe_poplevels): Don't expand_end_bindings. + (complete_start_java_method): Reorganize static initialization and + synchronization logic for source compiler. Remove pushlevel and + expand_start_bindings for byte compiler. + (end_java_method): Don't expand_end_bindings. Add static + initialization and synchronization logic for byte compiler. + Set cfun->x_whole_function_mode_p. + Call gimplify_function_tree and optimize_function_tree and + expand_expr_stmt. + (add_stmt_to_compound): New. + (java_add_stmt): New. + (java_add_local_var): New. + (get_stmts): New. + * parse.y (add_stmt_to_compound): Remove. + * jcf-parse.c (parse_class_file): Don't call expand_expr_stmt for + a native method -- we'll do that later. + +2003-07-27 Andreas Jaeger <aj@suse.de> + + * expr.c (build_expr_wfl): Convert remaining K&R prototypes + to ISO C90. + +2003-06-28 Jeff Sturm <jsturm@one-point.com> + + * java-gimplify.c (java_gimplify_block): Rebuild BLOCK_SUBBLOCKS. + * lang.c (flag_disable_gimple): Remove initialization. + +2003-06-23 Jeff Law <law@redhat.com> + + * Make-lang.in (java-gimplify.o): Add dependencies. + +2003-06-22 Jeff Sturm <jsturm@one-point.com> + + * parse.y (source_end_java_method): Don't attempt to inline + or optimize trees if flag_disable_gimple. + + * Make-lang.in (JAVA_OBJS): Remove java-tree-inline.o. + +2003-06-21 Jeff Sturm <jsturm@one-point.com> + + * Make-lang.in (JAVA_OBJS): Add java-gimplify.o. + + * decl.c (java_init_decl_processing): Initialize size_type_node. + (complete_start_java_method): Update DECL_SAVED_TREE. + (dump_function): Remove. + (java_optimize_inline): Remove. + + * expr.c (always_initialize_class_p): Initialize to 1. + (build_instanceof): Build proper boolean condition. + (build_class_init): Set DECL_INITIAL for init_test_decl. + (force_evaluation_order): Don't save_expr a void expr node. + + * java-gimplify.c: New file. + + * java-tree.h (java_gimplify_expr): Declare. + + * lang.c (java_tree_inlining_walk_subtrees): Remove declaration. + (flag_optimize_sci): Initialize to 0. + (LANG_HOOKS_TREE_INLINING_WALK_SUBTREES): Remove define. + (LANG_HOOKS_SIMPLIFY_EXPR): Add define. + (java_tree_inlining_walk_subtrees): Remove function. + (java_init): Set flag_disable_gimple to 1. + + * parse.y (source_end_java_method): Set cfun->x_whole_function_mode_p. + Gimplify. Optimize tree before expanding. Update comments. + (java_expand_method_bodies): Always save DECL_SAVED_TREE. + (patch_invoke): Don't save_expr force_evaluation_order result. + (patch_assignment): Use simpler compound expression. + (patch_if_else_statement): Don't optimize constant condition nodes. + +2003-03-02 Diego Novillo <dnovillo@redhat.com> + + * class.c: Replace DECL_SOURCE_FILE with TREE_FILENAME and + DECL_SOURCE_LINE with TREE_LINENO everywhere. + +2003-02-03 Diego Novillo <dnovillo@redhat.com> + + * parse.y (qualify_ambiguous_name): Initialize variable 'decl'. + +2003-01-15 Jeff Law <law@redhat.com> + + * class.c: Use TREE_FILENAME and TREE_LINENO to extract file/line + information from tree nodes. Use annotate_with_file_line to + annotate tree nodes with file/line information. + * decl.c, jcf-parse.c, jcf-write.c, parse.h: Likewise. + * parse.y: Likewise. + * expr.c (java_expand_expr): Handle EXPR_WITH_FILE_LOCATION nodes. + (build_expr_wfl): New function. + * java-tree.def (EXPR_WITH_FILE_LOCATION): New node. + * java-tree.h (EXPR_WFL_*): New macros. + (build_expr_wfl): Declare. + +Local Variables: +mode: change-log +change-log-default-name: "ChangeLog.tree-ssa" +End: diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in index fad423a..db3ac9d 100644 --- a/gcc/java/Make-lang.in +++ b/gcc/java/Make-lang.in @@ -105,7 +105,7 @@ JAVA_OBJS = java/parse.o java/class.o java/decl.o java/expr.o \ java/zextract.o java/jcf-io.o java/win32-host.o java/jcf-parse.o java/mangle.o \ java/mangle_name.o java/builtins.o java/resource.o \ java/jcf-write.o java/buffer.o java/check-init.o java/jcf-depend.o \ - java/jcf-path.o java/xref.o java/boehm.o java/java-tree-inline.o mkdeps.o + java/jcf-path.o java/xref.o java/boehm.o java/java-gimplify.o mkdeps.o GCJH_OBJS = java/gjavah.o java/jcf-io.o java/jcf-depend.o java/jcf-path.o \ java/win32-host.o java/zextract.o version.o mkdeps.o errors.o ggc-none.o \ @@ -333,6 +333,9 @@ java/xref.o: java/xref.c java/xref.h $(CONFIG_H) $(JAVA_TREE_H) toplev.h \ $(SYSTEM_H) coretypes.h $(TM_H) java/zextract.o: java/zextract.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ java/zipfile.h +java/java-gimplify.o: java/java-gimplify.c $(CONFIG_H) $(SYSTEM_H) \ + coretypes.h $(TM_H) $(JAVA_TREE_H) tree-simple.h toplev.h + java/parse-scan.o: java/parse-scan.c $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(TM_H) toplev.h $(JAVA_LEX_C) java/parse.h java/lex.h input.h java/parse.o: java/parse.c java/jcf-reader.c $(CONFIG_H) $(SYSTEM_H) \ diff --git a/gcc/java/builtins.c b/gcc/java/builtins.c index 1d3095f..77f0c58 100644 --- a/gcc/java/builtins.c +++ b/gcc/java/builtins.c @@ -124,7 +124,7 @@ java_build_function_call_expr (tree fn, tree arglist) call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - call_expr, arglist); + call_expr, arglist, NULL_TREE); TREE_SIDE_EFFECTS (call_expr) = 1; return fold (call_expr); } diff --git a/gcc/java/check-init.c b/gcc/java/check-init.c index c4e3948..f325c4e 100644 --- a/gcc/java/check-init.c +++ b/gcc/java/check-init.c @@ -770,7 +770,7 @@ check_init (tree exp, words before) break; case NOP_EXPR: - if (exp == empty_stmt_node) + if (IS_EMPTY_STMT (exp)) break; /* ... else fall through ... */ case UNARY_PLUS_EXPR: @@ -889,7 +889,7 @@ check_init (tree exp, words before) location_t saved_location = input_location; tree saved_wfl = wfl; tree body = EXPR_WFL_NODE (exp); - if (body == empty_stmt_node) + if (IS_EMPTY_STMT (body)) break; wfl = exp; input_filename = EXPR_WFL_FILENAME (exp); diff --git a/gcc/java/class.c b/gcc/java/class.c index 530b56f..137b647 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -890,6 +890,7 @@ build_utf8_ref (tree name) PUSH_FIELD_VALUE (cinit, "data", string); FINISH_RECORD_CONSTRUCTOR (cinit); TREE_CONSTANT (cinit) = 1; + TREE_INVARIANT (cinit) = 1; /* Generate a unique-enough identifier. */ sprintf(buf, "_Utf%d", ++utf8_count); @@ -940,8 +941,7 @@ build_indirect_class_ref (tree type) tree cl; index = alloc_class_constant (type); cl = build_ref_from_constant_pool (index); - TREE_TYPE (cl) = promote_type (class_ptr_type); - return cl; + return convert (promote_type (class_ptr_type), cl); } /* Build a reference to the class TYPE. @@ -1391,6 +1391,7 @@ get_dispatch_table (tree type, tree this_class_addr) tree fdesc = build (FDESC_EXPR, nativecode_ptr_type_node, method, build_int_2 (j, 0)); TREE_CONSTANT (fdesc) = 1; + TREE_INVARIANT (fdesc) = 1; list = tree_cons (NULL_TREE, fdesc, list); } else @@ -1731,7 +1732,8 @@ make_class_data (tree type) build1 (ADDR_EXPR, symbols_array_ptr_type, TYPE_OTABLE_SYMS_DECL (type))); TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1; - } + TREE_INVARIANT (TYPE_OTABLE_DECL (type)) = 1; + } if (TYPE_ATABLE_METHODS(type) == NULL_TREE) { PUSH_FIELD_VALUE (cons, "atable", null_pointer_node); @@ -1745,6 +1747,7 @@ make_class_data (tree type) build1 (ADDR_EXPR, symbols_array_ptr_type, TYPE_ATABLE_SYMS_DECL (type))); TREE_CONSTANT (TYPE_ATABLE_DECL (type)) = 1; + TREE_INVARIANT (TYPE_ATABLE_DECL (type)) = 1; } PUSH_FIELD_VALUE (cons, "catch_classes", @@ -1778,37 +1781,6 @@ make_class_data (tree type) void finish_class (void) { - tree method; - tree type_methods = TYPE_METHODS (current_class); - int saw_native_method = 0; - - /* Find out if we have any native methods. We use this information - later. */ - for (method = type_methods; - method != NULL_TREE; - method = TREE_CHAIN (method)) - { - if (METHOD_NATIVE (method)) - { - saw_native_method = 1; - break; - } - } - - /* Emit deferred inline methods. */ - for (method = type_methods; method != NULL_TREE; ) - { - if (! TREE_ASM_WRITTEN (method) && DECL_STRUCT_FUNCTION (method) != 0) - { - output_inline_function (method); - /* Scan the list again to see if there are any earlier - methods to emit. */ - method = type_methods; - continue; - } - method = TREE_CHAIN (method); - } - java_expand_catch_classes (current_class); current_function_decl = NULL_TREE; @@ -2376,6 +2348,7 @@ build_symbol_entry (tree decl) PUSH_FIELD_VALUE (sym, "signature", signature); FINISH_RECORD_CONSTRUCTOR (sym); TREE_CONSTANT (sym) = 1; + TREE_INVARIANT (sym) = 1; return sym; } @@ -2414,6 +2387,7 @@ emit_symbol_table (tree name, tree the_table, tree decl_list, tree the_syms_decl PUSH_FIELD_VALUE (null_symbol, "signature", null_pointer_node); FINISH_RECORD_CONSTRUCTOR (null_symbol); TREE_CONSTANT (null_symbol) = 1; + TREE_INVARIANT (null_symbol) = 1; list = tree_cons (NULL_TREE, null_symbol, list); /* Put the list in the right order and make it a constructor. */ diff --git a/gcc/java/constants.c b/gcc/java/constants.c index d97e8c0..32fc854 100644 --- a/gcc/java/constants.c +++ b/gcc/java/constants.c @@ -386,29 +386,35 @@ alloc_class_constant (tree clas) IDENTIFIER_LENGTH(class_name)))); } -/* Return a reference to the data array of the current constant pool. */ +/* Return the decl of the data array of the current constant pool. */ static tree build_constant_data_ref (void) { - tree cpool_data_ref = NULL_TREE; + tree decl = TYPE_CPOOL_DATA_REF (output_class); - if (TYPE_CPOOL_DATA_REF (output_class)) - cpool_data_ref = TYPE_CPOOL_DATA_REF (output_class); - - if (cpool_data_ref == NULL_TREE) + if (decl == NULL_TREE) { - tree decl; + tree type; tree decl_name = mangled_classname ("_CD_", output_class); - decl = build_decl (VAR_DECL, decl_name, - build_array_type (ptr_type_node, - one_elt_array_domain_type)); + + /* Build a type with unspecified bounds. The will make sure + that targets do the right thing with whatever size we end + up with at the end. Using bounds that are too small risks + assuming the data is in the small data section. */ + type = build_array_type (ptr_type_node, NULL_TREE); + + /* We need to lay out the type ourselves, since build_array_type + thinks the type is incomplete. */ + layout_type (type); + + decl = build_decl (VAR_DECL, decl_name, type); TREE_STATIC (decl) = 1; make_decl_rtl (decl, NULL); - TYPE_CPOOL_DATA_REF (output_class) = cpool_data_ref - = build1 (ADDR_EXPR, ptr_type_node, decl); + TYPE_CPOOL_DATA_REF (output_class) = decl; } - return cpool_data_ref; + + return decl; } /* Get the pointer value at the INDEX'th element of the constant pool. */ @@ -416,11 +422,9 @@ build_constant_data_ref (void) tree build_ref_from_constant_pool (int index) { - tree t = build_constant_data_ref (); - index *= int_size_in_bytes (ptr_type_node); - t = fold (build (PLUS_EXPR, ptr_type_node, - t, build_int_2 (index, 0))); - return build1 (INDIRECT_REF, ptr_type_node, t); + tree d = build_constant_data_ref (); + tree i = build_int_2 (index, 0); + return build (ARRAY_REF, TREE_TYPE (TREE_TYPE (d)), d, i); } /* Build an initializer for the constants field of the current constant pool. @@ -456,7 +460,7 @@ build_constants_constructor (void) tags_list = tree_cons (NULL_TREE, get_tag_node (0), tags_list); data_list = tree_cons (NULL_TREE, null_pointer_node, data_list); - data_decl = TREE_OPERAND (build_constant_data_ref (), 0); + data_decl = build_constant_data_ref (); TREE_TYPE (data_decl) = build_array_type (ptr_type_node, index_type), DECL_INITIAL (data_decl) = build_constructor (TREE_TYPE (data_decl), data_list); diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 047c0af..7a36e54 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -44,6 +44,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "java-except.h" #include "ggc.h" #include "timevar.h" +#include "cgraph.h" #include "tree-inline.h" #include "target.h" @@ -91,42 +92,58 @@ int current_pc; void indent (void) { - unsigned i; + int i; for (i = 0; i < binding_depth*2; i++) putc (' ', stderr); } #endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */ +/* Copy the value in decl into every alias in the same local variable + slot. */ +void +update_aliases (tree decl, int index) +{ + tree tmp = TREE_VEC_ELT (decl_map, index); + tree type = TREE_TYPE (decl); + while (tmp != NULL_TREE) + { + if (tmp != decl + && ! LOCAL_VAR_OUT_OF_SCOPE_P (tmp) + && TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp))) + { + tree src = build1 (NOP_EXPR, TREE_TYPE (tmp), decl); + java_add_stmt + (build (MODIFY_EXPR, TREE_TYPE (tmp), tmp, src)); + } + tmp = DECL_LOCAL_SLOT_CHAIN (tmp); + } +} + static tree push_jvm_slot (int index, tree decl) { - struct rtx_def *rtl = NULL; tree type = TREE_TYPE (decl); tree tmp; DECL_CONTEXT (decl) = current_function_decl; layout_decl (decl, 0); - /* See if we have an appropriate rtl (i.e. same mode) at this index. - If so, we must use it. */ + /* Look for another variable of the same mode in this slot. */ tmp = TREE_VEC_ELT (decl_map, index); while (tmp != NULL_TREE) { - if (TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp)) - && ! LOCAL_VAR_OUT_OF_SCOPE_P (tmp)) - rtl = DECL_RTL_IF_SET (tmp); - if (rtl != NULL) - break; - tmp = DECL_LOCAL_SLOT_CHAIN (tmp); - } - if (rtl != NULL) - SET_DECL_RTL (decl, rtl); - else - { - if (index >= DECL_MAX_LOCALS (current_function_decl)) - DECL_REGISTER (decl) = 1; - expand_decl (decl); + if (! LOCAL_VAR_OUT_OF_SCOPE_P (tmp) + && TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp))) + { + /* At the point of its creation this decl inherits whatever + is in the slot. */ + tree src = build1 (NOP_EXPR, TREE_TYPE (decl), tmp); + java_add_stmt + (build (MODIFY_EXPR, TREE_TYPE (decl), decl, src)); + break; + } + tmp = DECL_LOCAL_SLOT_CHAIN (tmp); } /* Now link the decl into the decl_map. */ @@ -139,6 +156,9 @@ push_jvm_slot (int index, tree decl) } DECL_LOCAL_SLOT_CHAIN (decl) = TREE_VEC_ELT (decl_map, index); TREE_VEC_ELT (decl_map, index) = decl; + + if (TREE_CODE (decl) != PARM_DECL) + pushdecl (decl); return decl; } @@ -201,11 +221,16 @@ find_local_variable (int index, tree type, int pc) /* Scan through every declaration that has been created in this slot. */ while (decl != NULL_TREE) { + bool has_name = false; + tree name = DECL_NAME (decl); + if (name && IDENTIFIER_POINTER (name)) + has_name = IDENTIFIER_POINTER (name)[0] != '#'; + /* Variables created in give_name_to_locals() have a name and have a specified scope, so we can handle them specifically. We want to use the specific decls created for those so they are assigned the right variables in the debugging information. */ - if (DECL_NAME (decl) != NULL_TREE) + if (has_name) { /* This is a variable we have a name for, so it has a scope supplied in the class file. But it only matters when we @@ -230,8 +255,20 @@ find_local_variable (int index, tree type, int pc) if (best != NULL_TREE) return best; - /* If we don't find a match, create one with the type passed in. */ - return push_jvm_slot (index, build_decl (VAR_DECL, NULL_TREE, type)); + /* If we don't find a match, create one with the type passed in. + Ths name of the variable is #n#m, which n is the variable index + in the local variable area and m is a dummy identifier for + uniqueness -- multiple variables may share the same local + variable index. */ + { + char buf[64]; + tree name; + static int uniq; + sprintf (buf, "#%d#%d", index, uniq++); + name = get_identifier (buf); + + return push_jvm_slot (index, build_decl (VAR_DECL, name, type)); + } } @@ -274,6 +311,9 @@ struct binding_level /* The bytecode PC that marks the start of this level. */ int start_pc; + /* The statements in this binding level. */ + tree stmts; + #if defined(DEBUG_JAVA_BINDING_LEVELS) /* Binding depth at which this level began. */ unsigned binding_depth; @@ -304,7 +344,11 @@ static struct binding_level *global_binding_level; static const struct binding_level clear_binding_level = {NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, - NULL_BINDING_LEVEL, LARGEST_PC, 0}; + NULL_BINDING_LEVEL, LARGEST_PC, 0, NULL, +#if defined(DEBUG_JAVA_BINDING_LEVELS) + 0, +#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */ +}; #if 0 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function @@ -439,7 +483,10 @@ java_init_decl_processing (void) pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned long"), unsigned_long_type_node)); - set_sizetype (make_unsigned_type (POINTER_SIZE)); + /* This is not a java type, however tree-dfa requires a definition for + size_type_node. */ + size_type_node = make_unsigned_type (POINTER_SIZE); + set_sizetype (size_type_node); /* Define these next since types below may used them. */ integer_type_node = java_type_for_size (INT_TYPE_SIZE, 0); @@ -483,10 +530,6 @@ java_init_decl_processing (void) null_pointer_node = build_int_2 (0, 0); TREE_TYPE (null_pointer_node) = ptr_type_node; - /* Used by the parser to represent empty statements and blocks. */ - empty_stmt_node = build1 (NOP_EXPR, void_type_node, size_zero_node); - CAN_COMPLETE_NORMALLY (empty_stmt_node) = 1; - #if 0 /* Make a type to be the domain of a few array types whose domains don't really matter. @@ -1194,7 +1237,7 @@ pushlevel (int unused ATTRIBUTE_UNUSED) #if defined(DEBUG_JAVA_BINDING_LEVELS) newlevel->binding_depth = binding_depth; indent (); - fprintf (stderr, "push %s level 0x%08x pc %d\n", + fprintf (stderr, "push %s level %p pc %d\n", (is_class_level) ? "class" : "block", newlevel, current_pc); is_class_level = 0; binding_depth++; @@ -1226,18 +1269,18 @@ poplevel (int keep, int reverse, int functionbody) tree subblocks = current_binding_level->blocks; tree block = 0; tree decl; + tree bind = 0; int block_previously_created; - { #if defined(DEBUG_JAVA_BINDING_LEVELS) binding_depth--; indent (); if (current_binding_level->end_pc != LARGEST_PC) - fprintf (stderr, "pop %s level 0x%08x pc %d (end pc %d)\n", + fprintf (stderr, "pop %s level %p pc %d (end pc %d)\n", (is_class_level) ? "class" : "block", current_binding_level, current_pc, current_binding_level->end_pc); else - fprintf (stderr, "pop %s level 0x%08x pc %d\n", + fprintf (stderr, "pop %s level %p pc %d\n", (is_class_level) ? "class" : "block", current_binding_level, current_pc); #if 0 if (is_class_level != (current_binding_level == class_binding_level)) @@ -1259,37 +1302,11 @@ poplevel (int keep, int reverse, int functionbody) else decls = current_binding_level->names; - /* Output any nested inline functions within this block - if they weren't already output. */ - for (decl = decls; decl; decl = TREE_CHAIN (decl)) - if (TREE_CODE (decl) == FUNCTION_DECL - && ! TREE_ASM_WRITTEN (decl) - && DECL_INITIAL (decl) != 0 - && TREE_ADDRESSABLE (decl)) - { - /* If this decl was copied from a file-scope decl on account - of a block-scope extern decl, propagate TREE_ADDRESSABLE - to the file-scope decl. - - DECL_ABSTRACT_ORIGIN can be set to itself if - warn_return_type is true, since then the decl goes - through save_for_inline_copying. */ - if (DECL_ABSTRACT_ORIGIN (decl) != 0 - && DECL_ABSTRACT_ORIGIN (decl) != decl) - TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1; - else - { - push_function_context (); - output_inline_function (decl); - pop_function_context (); - } - } - else if (TREE_CODE (decl) == VAR_DECL - && DECL_LANG_SPECIFIC (decl) != NULL - && DECL_LOCAL_SLOT_NUMBER (decl)) - LOCAL_VAR_OUT_OF_SCOPE_P (decl) = 1; - } + if (TREE_CODE (decl) == VAR_DECL + && DECL_LANG_SPECIFIC (decl) != NULL + && DECL_LOCAL_SLOT_NUMBER (decl)) + LOCAL_VAR_OUT_OF_SCOPE_P (decl) = 1; /* If there were any declarations in that level, or if this level is a function body, @@ -1300,12 +1317,55 @@ poplevel (int keep, int reverse, int functionbody) if (block_previously_created) block = current_binding_level->this_block; else if (keep || functionbody) - block = make_node (BLOCK); + { + block = make_node (BLOCK); + TREE_TYPE (block) = void_type_node; + } + if (block != 0) { - BLOCK_VARS (block) = decls; + /* If any statements have been generated at this level, create a + BIND_EXPR to hold them and copy the variables to it. This + only applies to the bytecode compiler. */ + if (current_binding_level->stmts) + { + tree decl = decls; + tree *var = &BLOCK_VARS (block); + + /* Copy decls from names list, ignoring labels. */ + while (decl) + { + tree next = TREE_CHAIN (decl); + if (TREE_CODE (decl) != LABEL_DECL) + { + *var = decl; + var = &TREE_CHAIN (decl); + } + decl = next; + } + *var = NULL; + + bind = build (BIND_EXPR, TREE_TYPE (block), BLOCK_VARS (block), + BLOCK_EXPR_BODY (block), block); + + BIND_EXPR_BODY (bind) = current_binding_level->stmts; + + if (BIND_EXPR_BODY (bind) + && TREE_SIDE_EFFECTS (BIND_EXPR_BODY (bind))) + TREE_SIDE_EFFECTS (bind) = 1; + + /* FIXME: gimplifier brain damage. */ + if (BIND_EXPR_BODY (bind) == NULL) + BIND_EXPR_BODY (bind) = build_java_empty_stmt (); + + current_binding_level->stmts = NULL; + } + else + { + BLOCK_VARS (block) = decls; + } BLOCK_SUBBLOCKS (block) = subblocks; - } + } /* In each subblock, record that this is its superior. */ @@ -1390,7 +1450,10 @@ poplevel (int keep, int reverse, int functionbody) /* Dispose of the block that we just made inside some higher level. */ if (functionbody) - DECL_INITIAL (current_function_decl) = block; + { + DECL_INITIAL (current_function_decl) = block; + DECL_SAVED_TREE (current_function_decl) = bind; + } else if (block) { if (!block_previously_created) @@ -1406,21 +1469,9 @@ poplevel (int keep, int reverse, int functionbody) current_binding_level->blocks = chainon (current_binding_level->blocks, subblocks); - /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this - binding contour so that they point to the appropriate construct, i.e. - either to the current FUNCTION_DECL node, or else to the BLOCK node - we just constructed. - - Note that for tagged types whose scope is just the formal parameter - list for some function type specification, we can't properly set - their TYPE_CONTEXTs here, because we don't have a pointer to the - appropriate FUNCTION_TYPE node readily available to us. For those - cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set - in `grokdeclarator' as soon as we have created the FUNCTION_TYPE - node which will represent the "scope" for these "parameter list local" - tagged types. - */ - + if (bind) + java_add_stmt (bind); + if (block) TREE_USED (block) = 1; return block; @@ -1437,7 +1488,7 @@ maybe_pushlevels (int pc) DECL_LOCAL_START_PC (pending_local_decls) <= pc) { tree *ptr = &pending_local_decls; - tree decl = *ptr; + tree decl = *ptr, next; int end_pc = DECL_LOCAL_END_PC (decl); while (*ptr != NULL_TREE @@ -1454,13 +1505,13 @@ maybe_pushlevels (int pc) maybe_start_try (pc, end_pc); pushlevel (1); - expand_start_bindings (0); current_binding_level->end_pc = end_pc; current_binding_level->start_pc = pc; - current_binding_level->names = decl; - for ( ; decl != NULL_TREE; decl = TREE_CHAIN (decl)) + current_binding_level->names = NULL; + for ( ; decl != NULL_TREE; decl = next) { + next = TREE_CHAIN (decl); push_jvm_slot (DECL_LOCAL_SLOT_NUMBER (decl), decl); } } @@ -1477,7 +1528,6 @@ maybe_poplevels (int pc) while (current_binding_level->end_pc <= pc) { - expand_end_bindings (getdecls (), 1, 0); maybe_end_try (current_binding_level->start_pc, pc); poplevel (1, 0, 0); } @@ -1583,7 +1633,7 @@ give_name_to_locals (JCF *jcf) if (end_pc > DECL_CODE_LENGTH (current_function_decl)) { warning ("%Jbad PC range for debug info for local '%D'", - decl, decl); + decl, decl); end_pc = DECL_CODE_LENGTH (current_function_decl); } @@ -1662,78 +1712,6 @@ build_result_decl (tree fndecl) } void -complete_start_java_method (tree fndecl) -{ - if (! flag_emit_class_files) - { - /* Initialize the RTL code for the function. */ - init_function_start (fndecl); - - /* Set up parameters and prepare for return, for the function. */ - expand_function_start (fndecl, 0); - } - -#if 0 - /* If this fcn was already referenced via a block-scope `extern' decl (or - an implicit decl), propagate certain information about the usage. */ - if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl))) - TREE_ADDRESSABLE (current_function_decl) = 1; - -#endif - - if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl) - && ! flag_emit_class_files - && ! DECL_CLINIT_P (fndecl) - && ! CLASS_INTERFACE (TYPE_NAME (current_class))) - { - tree clas = DECL_CONTEXT (fndecl); - tree init = build (CALL_EXPR, void_type_node, - build_address_of (soft_initclass_node), - build_tree_list (NULL_TREE, build_class_ref (clas)), - NULL_TREE); - TREE_SIDE_EFFECTS (init) = 1; - expand_expr_stmt (init); - } - - /* Push local variables. Function compiled from source code are - using a different local variables management, and for them, - pushlevel shouldn't be called from here. */ - if (!CLASS_FROM_SOURCE_P (DECL_CONTEXT (fndecl))) - { - pushlevel (2); - if (! flag_emit_class_files) - expand_start_bindings (1); - } - - if (METHOD_SYNCHRONIZED (fndecl) && ! flag_emit_class_files) - { - /* Wrap function body with a monitorenter plus monitorexit cleanup. */ - tree enter, exit, lock; - if (METHOD_STATIC (fndecl)) - lock = build_class_ref (DECL_CONTEXT (fndecl)); - else - lock = DECL_ARGUMENTS (fndecl); - BUILD_MONITOR_ENTER (enter, lock); - BUILD_MONITOR_EXIT (exit, lock); - if (!CLASS_FROM_SOURCE_P (DECL_CONTEXT (fndecl))) - { - expand_expr_stmt (enter); - expand_decl_cleanup (NULL_TREE, exit); - } - else - { - tree function_body = DECL_FUNCTION_BODY (fndecl); - tree body = BLOCK_EXPR_BODY (function_body); - lock = build (COMPOUND_EXPR, void_type_node, - enter, - build (TRY_FINALLY_EXPR, void_type_node, body, exit)); - TREE_SIDE_EFFECTS (lock) = 1; - BLOCK_EXPR_BODY (function_body) = lock; - } - } -} - -void start_java_method (tree fndecl) { tree tem, *ptr; @@ -1789,7 +1767,9 @@ start_java_method (tree fndecl) type_map[i++] = NULL_TREE; build_result_decl (fndecl); - complete_start_java_method (fndecl); + + /* Push local variables. */ + pushlevel (2); } void @@ -1797,7 +1777,6 @@ end_java_method (void) { tree fndecl = current_function_decl; - expand_end_bindings (getdecls (), 1, 0); /* pop out of function */ poplevel (1, 1, 0); @@ -1806,64 +1785,71 @@ end_java_method (void) BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; - /* Generate rtl for function exit. */ - expand_function_end (); - - /* Run the optimizers and output assembler code for this function. */ - rest_of_compilation (fndecl); + flag_unit_at_a_time = 0; + finish_method (fndecl); current_function_decl = NULL_TREE; } -/* Expand a function's body. */ +/* Prepare a method for expansion. */ void -java_expand_body (tree fndecl) +finish_method (tree fndecl) { - location_t saved_location = input_location; - - current_function_decl = fndecl; - input_location = DECL_SOURCE_LOCATION (fndecl); - output_class = current_class = DECL_CONTEXT (fndecl); + tree *tp = &DECL_SAVED_TREE (fndecl); - timevar_push (TV_EXPAND); - - /* Prepare the function for tree completion. */ - start_complete_expand_method (fndecl); - - if (! flag_emit_class_files && ! flag_emit_xref) + /* Wrap body of synchronized methods in a monitorenter, + plus monitorexit cleanup. */ + if (METHOD_SYNCHRONIZED (fndecl)) { - /* Initialize the RTL code for the function. */ - init_function_start (fndecl); - - /* Set up parameters and prepare for return, for the function. */ - expand_function_start (fndecl, 0); - - /* Generate the RTL for this function. */ - expand_expr_stmt_value (DECL_SAVED_TREE (fndecl), 0, 1); + tree enter, exit, lock; + if (METHOD_STATIC (fndecl)) + lock = build_class_ref (DECL_CONTEXT (fndecl)); + else + lock = DECL_ARGUMENTS (fndecl); + BUILD_MONITOR_ENTER (enter, lock); + BUILD_MONITOR_EXIT (exit, lock); + *tp = build (COMPOUND_EXPR, void_type_node, + enter, + build (TRY_FINALLY_EXPR, void_type_node, *tp, exit)); } - /* Pop out of its parameters. */ - pushdecl_force_head (DECL_ARGUMENTS (fndecl)); - poplevel (1, 0, 1); - BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; - - if (! flag_emit_class_files && ! flag_emit_xref) + /* Prepend class initialization for static methods reachable from + other classes. */ + if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl) + && ! DECL_CLINIT_P (fndecl) + && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl)))) { - /* Generate RTL for function exit. */ - input_line = DECL_FUNCTION_LAST_LINE (fndecl); - expand_function_end (); - - /* Run the optimizers and output the assembler code - for this function. */ - rest_of_compilation (fndecl); + tree clas = DECL_CONTEXT (fndecl); + tree init = build (CALL_EXPR, void_type_node, + build_address_of (soft_initclass_node), + build_tree_list (NULL_TREE, build_class_ref (clas)), + NULL_TREE); + *tp = build (COMPOUND_EXPR, TREE_TYPE (*tp), init, *tp); } - timevar_pop (TV_EXPAND); + /* Convert function tree to GENERIC prior to inlining. */ + java_genericize (fndecl); - input_location = saved_location; + /* Store the end of the function, so that we get good line number + info for the epilogue. */ + if (DECL_STRUCT_FUNCTION (fndecl)) + cfun = DECL_STRUCT_FUNCTION (fndecl); + else + allocate_struct_function (fndecl); + cfun->function_end_locus.file = DECL_SOURCE_FILE (fndecl); + cfun->function_end_locus.line = DECL_FUNCTION_LAST_LINE (fndecl); - current_function_decl = NULL_TREE; + /* Defer inlining and expansion to the cgraph optimizers. */ + cgraph_finalize_function (fndecl, false); +} + +/* Optimize and expand a function's entire body. */ + +void +java_expand_body (tree fndecl) +{ + tree_rest_of_compilation (fndecl, 0); } /* We pessimistically marked all methods and fields external until we @@ -1895,4 +1881,62 @@ java_mark_class_local (tree class) java_mark_decl_local (t); } +/* Add a statement to a compound_expr. */ + +tree +add_stmt_to_compound (existing, type, stmt) + tree existing, type, stmt; +{ + if (!stmt) + return existing; + else if (existing) + { + tree expr = build (COMPOUND_EXPR, type, existing, stmt); + TREE_SIDE_EFFECTS (expr) + = TREE_SIDE_EFFECTS (existing) | TREE_SIDE_EFFECTS (stmt); + return expr; + } + else + return stmt; +} + +/* Add a statement to the compound_expr currently being + constructed. */ + +tree +java_add_stmt (stmt) + tree stmt; +{ + if (input_filename) + annotate_with_locus (stmt, input_location); + + return current_binding_level->stmts + = add_stmt_to_compound (current_binding_level->stmts, + TREE_TYPE (stmt), stmt); +} + +/* Add a variable to the current scope. */ + +tree +java_add_local_var (tree decl) +{ + tree *vars = ¤t_binding_level->names; + tree next = *vars; + TREE_CHAIN (decl) = next; + *vars = decl; + DECL_CONTEXT (decl) = current_function_decl; + MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); + return decl; +} + +/* Return a pointer to the compound_expr currently being + constructed. */ + +tree * +get_stmts (void) +{ + return ¤t_binding_level->stmts; +} + + #include "gt-java-decl.h" diff --git a/gcc/java/except.c b/gcc/java/except.c index c5c7dcf..b77842e 100644 --- a/gcc/java/except.c +++ b/gcc/java/except.c @@ -170,6 +170,7 @@ link_handler (struct eh_range *range, struct eh_range *outer) TREE_VALUE (range->handlers)); h->next_sibling = NULL; h->expanded = 0; + h->stmt = NULL; /* Restart both from the top to avoid having to make this function smart about reentrancy. */ link_handler (h, &whole_range); @@ -287,6 +288,7 @@ add_handler (int start_pc, int end_pc, tree handler, tree type) h->handlers = build_tree_list (type, handler); h->next_sibling = NULL; h->expanded = 0; + h->stmt = NULL; if (prev == NULL) whole_range.first_child = h; @@ -294,7 +296,6 @@ add_handler (int start_pc, int end_pc, tree handler, tree type) prev->next_sibling = h; } - /* if there are any handlers for this range, issue start of region */ static void expand_start_java_handler (struct eh_range *range) @@ -304,8 +305,14 @@ expand_start_java_handler (struct eh_range *range) fprintf (stderr, "expand start handler pc %d --> %d\n", current_pc, range->end_pc); #endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */ + { + tree new = build (TRY_CATCH_EXPR, void_type_node, NULL, NULL); + TREE_SIDE_EFFECTS (new) = 1; + java_add_stmt (build_java_empty_stmt ()); + range->stmt = java_add_stmt (new); + } + range->expanded = 1; - expand_eh_region_start (); } tree @@ -348,7 +355,7 @@ prepare_eh_table_type (tree type) DECL_INITIAL (decl) = build_class_ref (type); layout_decl (decl, 0); pushdecl (decl); - exp = build1 (ADDR_EXPR, ptr_type_node, decl); + exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (decl)), decl); } else { @@ -370,6 +377,8 @@ prepare_eh_table_type (tree type) TYPE_CATCH_CLASSES (output_class)); } + exp = convert (ptr_type_node, exp); + *slot = tree_cons (type, exp, NULL_TREE); return exp; @@ -379,7 +388,10 @@ static int expand_catch_class (void **entry, void *x ATTRIBUTE_UNUSED) { struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry; - tree decl = TREE_OPERAND (TREE_VALUE ((tree)ite->value), 0); + tree addr = TREE_VALUE ((tree)ite->value); + tree decl; + STRIP_NOPS (addr); + decl = TREE_OPERAND (addr, 0); rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0); return true; } @@ -420,8 +432,9 @@ static void expand_end_java_handler (struct eh_range *range) { tree handler = range->handlers; - force_poplevels (range->start_pc); - expand_start_all_catch (); + tree compound = NULL; + + force_poplevels (range->start_pc); for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler)) { /* For bytecode we treat exceptions a little unusually. A @@ -431,14 +444,56 @@ expand_end_java_handler (struct eh_range *range) extra (and difficult) work to get this to look like a gcc-style finally clause. */ tree type = TREE_PURPOSE (handler); + if (type == NULL) type = throwable_type_node; - expand_start_catch (prepare_eh_table_type (type)); - expand_goto (TREE_VALUE (handler)); - expand_end_catch (); + type = prepare_eh_table_type (type); + + if (compound) + { + /* If we already have a COMPOUND there is more than one + catch handler for this try block. Wrap the + TRY_CATCH_EXPR in operand 1 of COMPOUND with another + TRY_CATCH_EXPR. */ + tree inner_try_expr = TREE_OPERAND (compound, 1); + tree catch_expr + = build (CATCH_EXPR, void_type_node, type, + build (GOTO_EXPR, void_type_node, TREE_VALUE (handler))); + tree try_expr + = build (TRY_CATCH_EXPR, void_type_node, + inner_try_expr, catch_expr); + TREE_OPERAND (compound, 1) = try_expr; + } + else + { + tree *stmts = get_stmts (); + tree outer; + tree try_expr; + compound = range->stmt; + outer = TREE_OPERAND (compound, 0); + try_expr = TREE_OPERAND (compound, 1); + /* On the left of COMPOUND is the expresion to be evaluated + before the try handler is entered; on the right is a + TRY_FINALLY_EXPR with no operands as yet. In the current + statement list is an expression that we're going to move + inside the try handler. We'll create a new COMPOUND_EXPR + with the outer context on the left and the TRY_FINALLY_EXPR + on the right, then nullify both operands of COMPOUND, which + becomes the final expression in OUTER. This new compound + expression replaces the current statement list. */ + TREE_OPERAND (try_expr, 0) = *stmts; + TREE_OPERAND (try_expr, 1) + = build (CATCH_EXPR, void_type_node, type, + build (GOTO_EXPR, void_type_node, TREE_VALUE (handler))); + TREE_SIDE_EFFECTS (try_expr) = 1; + TREE_OPERAND (compound, 0) = build_java_empty_stmt (); + TREE_OPERAND (compound, 1) = build_java_empty_stmt (); + compound + = build (COMPOUND_EXPR, TREE_TYPE (try_expr), outer, try_expr); + *stmts = compound; + } } - expand_end_all_catch (); #if defined(DEBUG_JAVA_BINDING_LEVELS) indent (); fprintf (stderr, "expand end handler pc %d <-- %d\n", diff --git a/gcc/java/expr.c b/gcc/java/expr.c index 11f6c94..a63309e 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -43,6 +43,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "toplev.h" #include "except.h" #include "ggc.h" +#include "tree-simple.h" #include "target.h" static void flush_quick_stack (void); @@ -71,6 +72,8 @@ static void expand_compare (enum tree_code, tree, tree, int); static void expand_test (enum tree_code, tree, int); static void expand_cond (enum tree_code, tree, int); static void expand_java_goto (int); +static tree expand_java_switch (tree, int); +static void expand_java_add_case (tree, int, int); #if 0 static void expand_java_call (int, int); static void expand_java_ret (tree); @@ -94,7 +97,8 @@ tree dtable_ident = NULL_TREE; /* Set to nonzero value in order to emit class initialization code before static field references. */ -int always_initialize_class_p; +/* FIXME: Make this work with gimplify. */ +int always_initialize_class_p = 1; /* We store the stack state in two places: Within a basic block, we use the quick_stack, which is a @@ -231,7 +235,7 @@ flush_quick_stack (void) decl = find_stack_slot (stack_index, type); if (decl != node) - expand_assignment (decl, node, 0); + java_add_stmt (build (MODIFY_EXPR, TREE_TYPE (node), decl, node)); stack_index += 1 + TYPE_IS_WIDE (type); } } @@ -489,7 +493,7 @@ static void java_stack_swap (void) { tree type1, type2; - rtx temp; + tree temp; tree decl1, decl2; if (stack_pointer < 2 @@ -503,10 +507,15 @@ java_stack_swap (void) flush_quick_stack (); 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 (find_stack_slot (stack_pointer - 1, type2)), - DECL_RTL (decl2)); - emit_move_insn (DECL_RTL (find_stack_slot (stack_pointer - 2, type1)), temp); + temp = build_decl (VAR_DECL, NULL_TREE, type1); + java_add_local_var (temp); + java_add_stmt (build (MODIFY_EXPR, type1, temp, decl1)); + java_add_stmt (build (MODIFY_EXPR, type2, + find_stack_slot (stack_pointer - 1, type2), + decl2)); + java_add_stmt (build (MODIFY_EXPR, type1, + find_stack_slot (stack_pointer - 2, type1), + temp)); stack_type_map[stack_pointer - 1] = type2; stack_type_map[stack_pointer - 2] = type1; } @@ -550,7 +559,9 @@ java_stack_dup (int size, int offset) { tree src_decl = find_stack_slot (src_index, type); tree dst_decl = find_stack_slot (dst_index, type); - emit_move_insn (DECL_RTL (dst_decl), DECL_RTL (src_decl)); + + java_add_stmt + (build (MODIFY_EXPR, TREE_TYPE (dst_decl), dst_decl, src_decl)); stack_type_map[dst_index] = type; } } @@ -570,7 +581,7 @@ build_java_athrow (tree node) build_tree_list (NULL_TREE, node), NULL_TREE); TREE_SIDE_EFFECTS (call) = 1; - expand_expr_stmt (call); + java_add_stmt (call); java_stack_pop (stack_pointer); } @@ -584,16 +595,17 @@ build_java_jsr (int target_pc, int return_pc) tree ret_label = fold (build1 (ADDR_EXPR, return_address_type_node, ret)); push_value (ret_label); flush_quick_stack (); - emit_jump (label_rtx (where)); - expand_label (ret); - if (instruction_bits [return_pc] & BCODE_VERIFIED) - load_type_state (ret); + java_add_stmt (build (GOTO_EXPR, void_type_node, where)); + + /* Do not need to emit the label here. We noted the existance of the + label as a jump target in note_instructions; we'll emit the label + for real at the beginning of the expand_byte_code loop. */ } static void build_java_ret (tree location) { - expand_computed_goto (location); + java_add_stmt (build (GOTO_EXPR, void_type_node, location)); } /* Implementation of operations on array: new, load, store, length */ @@ -713,7 +725,10 @@ java_check_reference (tree expr, int check) tree build_java_indirect_ref (tree type, tree expr, int check) { - return build1 (INDIRECT_REF, type, java_check_reference (expr, check)); + tree t; + t = java_check_reference (expr, check); + t = convert (build_pointer_type (type), t); + return build1 (INDIRECT_REF, type, t); } /* Implement array indexing (either as l-value or r-value). @@ -978,13 +993,11 @@ expand_java_arraystore (tree rhs_type_node) if (TREE_CODE (rhs_type_node) == POINTER_TYPE) { tree check = build_java_arraystore_check (array, rhs_node); - expand_expr_stmt (check); + java_add_stmt (check); } - expand_assignment (build_java_arrayaccess (array, - rhs_type_node, - index), - rhs_node, 0); + array = build_java_arrayaccess (array, rhs_type_node, index); + java_add_stmt (build (MODIFY_EXPR, TREE_TYPE (array), array, rhs_node)); } /* Expand the evaluation of ARRAY[INDEX]. build_java_check_indexed_type makes @@ -1077,7 +1090,7 @@ static void expand_java_return (tree type) { if (type == void_type_node) - expand_null_return (); + java_add_stmt (build (RETURN_EXPR, void_type_node, NULL)); else { tree retval = pop_value (type); @@ -1094,7 +1107,7 @@ expand_java_return (tree type) retval = build1(NOP_EXPR, TREE_TYPE(res), retval); TREE_SIDE_EFFECTS (retval) = 1; - expand_return (retval); + java_add_stmt (build (RETURN_EXPR, TREE_TYPE (retval), retval)); } } @@ -1111,13 +1124,9 @@ expand_load_internal (int index, tree type, int pc) value into it. Then we push this new local on the stack. Hopefully this all gets optimized out. */ copy = build_decl (VAR_DECL, NULL_TREE, type); - DECL_CONTEXT (copy) = current_function_decl; - layout_decl (copy, 0); - DECL_REGISTER (copy) = 1; - expand_decl (copy); - MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (copy); - DECL_INITIAL (copy) = var; - expand_decl_init (copy); + java_add_local_var (copy); + java_add_stmt (build (MODIFY_EXPR, TREE_TYPE (var), copy, var)); + push_value (copy); } @@ -1220,7 +1229,8 @@ build_instanceof (tree value, tree type) { tree save = save_expr (value); expr = build (COND_EXPR, itype, - save, + build (NE_EXPR, boolean_type_node, + save, null_pointer_node), build (EQ_EXPR, itype, build_get_class (save), build_class_ref (type)), @@ -1269,7 +1279,8 @@ expand_iinc (unsigned int local_var_index, int ival, int pc) 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); + java_add_stmt (build (MODIFY_EXPR, TREE_TYPE (local_var), local_var, res)); + update_aliases (local_var, local_var_index); } @@ -1552,7 +1563,6 @@ lookup_label (int pc) /* The type of the address of a label is return_address_type_node. */ tree decl = create_label_decl (name); LABEL_PC (decl) = pc; - label_rtx (decl); return pushdecl (decl); } } @@ -1600,9 +1610,10 @@ expand_compare (enum tree_code condition, tree value1, tree value2, { tree target = lookup_label (target_pc); tree cond = fold (build (condition, boolean_type_node, value1, value2)); - expand_start_cond (java_truthvalue_conversion (cond), 0); - expand_goto (target); - expand_end_cond (); + java_add_stmt + (build (COND_EXPR, void_type_node, java_truthvalue_conversion (cond), + build (GOTO_EXPR, void_type_node, target), + build_java_empty_stmt ())); } /* Emit code for a TEST-type opcode. */ @@ -1636,7 +1647,43 @@ expand_java_goto (int target_pc) { tree target_label = lookup_label (target_pc); flush_quick_stack (); - expand_goto (target_label); + java_add_stmt (build (GOTO_EXPR, void_type_node, target_label)); +} + +static tree +expand_java_switch (tree selector, int default_pc) +{ + tree switch_expr, x; + + flush_quick_stack (); + switch_expr = build (SWITCH_EXPR, TREE_TYPE (selector), selector, + NULL_TREE, NULL_TREE); + java_add_stmt (switch_expr); + + x = build (CASE_LABEL_EXPR, void_type_node, NULL_TREE, NULL_TREE, + create_artificial_label ()); + append_to_statement_list (x, &SWITCH_BODY (switch_expr)); + + x = build (GOTO_EXPR, void_type_node, lookup_label (default_pc)); + append_to_statement_list (x, &SWITCH_BODY (switch_expr)); + + return switch_expr; +} + +static void +expand_java_add_case (tree switch_expr, int match, int target_pc) +{ + tree value, x; + + value = build_int_2 (match, match < 0 ? -1 : 0); + TREE_TYPE (value) = TREE_TYPE (switch_expr); + + x = build (CASE_LABEL_EXPR, void_type_node, value, NULL_TREE, + create_artificial_label ()); + append_to_statement_list (x, &SWITCH_BODY (switch_expr)); + + x = build (GOTO_EXPR, void_type_node, lookup_label (target_pc)); + append_to_statement_list (x, &SWITCH_BODY (switch_expr)); } #if 0 @@ -1728,6 +1775,7 @@ build_class_init (tree clas, tree expr) optimizing class initialization. */ if (!STATIC_CLASS_INIT_OPT_P ()) DECL_BIT_INDEX(*init_test_decl) = -1; + DECL_INITIAL (*init_test_decl) = integer_zero_node; /* Don't emit any symbolic debugging info for this decl. */ DECL_IGNORED_P (*init_test_decl) = 1; } @@ -1769,7 +1817,8 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED, || (!TREE_PUBLIC (method) && DECL_CONTEXT (method))) { make_decl_rtl (method, NULL); - func = build1 (ADDR_EXPR, method_ptr_type_node, method); + func = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (method)), + method); } else { @@ -1780,6 +1829,7 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED, build (ARRAY_REF, method_ptr_type_node, TYPE_ATABLE_DECL (output_class), table_index); } + func = convert (method_ptr_type_node, func); } else { @@ -2086,7 +2136,11 @@ expand_invoke (int opcode, int method_ref_index, int nargs ATTRIBUTE_UNUSED) else func = build_invokeinterface (dtable, method); } - func = build1 (NOP_EXPR, build_pointer_type (method_type), func); + + if (TREE_CODE (func) == ADDR_EXPR) + TREE_TYPE (func) = build_pointer_type (method_type); + else + func = build1 (NOP_EXPR, build_pointer_type (method_type), func); call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE); TREE_SIDE_EFFECTS (call) = 1; @@ -2099,7 +2153,7 @@ expand_invoke (int opcode, int method_ref_index, int nargs ATTRIBUTE_UNUSED) } if (TREE_CODE (TREE_TYPE (method_type)) == VOID_TYPE) - expand_expr_stmt (call); + java_add_stmt (call); else { push_value (call); @@ -2118,6 +2172,7 @@ build_jni_stub (tree method) tree env_var, res_var = NULL_TREE, block; tree method_args, res_type; tree meth_var; + tree bind; int args_size = 0; @@ -2151,9 +2206,7 @@ build_jni_stub (tree method) DECL_INITIAL (meth_var) = null_pointer_node; TREE_USED (meth_var) = 1; chainon (env_var, meth_var); - layout_decl (meth_var, 0); - make_decl_rtl (meth_var, NULL); - rest_of_decl_compilation (meth_var, NULL, 0, 0); + build_result_decl (method); /* One strange way that the front ends are different is that they store arguments differently. */ @@ -2269,39 +2322,31 @@ build_jni_stub (tree method) body = build (COMPOUND_EXPR, void_type_node, body, call); TREE_SIDE_EFFECTS (body) = 1; - /* Finally, do the return. When compiling from source we rely on - patch_return to patch the return value -- because DECL_RESULT is - not set at the time this function is called. */ - if (from_class) - { - res_type = void_type_node; - if (res_var != NULL_TREE) - { - tree drt; - if (! DECL_RESULT (method)) - abort (); - /* Make sure we copy the result variable to the actual - result. We use the type of the DECL_RESULT because it - might be different from the return type of the function: - it might be promoted. */ - drt = TREE_TYPE (DECL_RESULT (method)); - if (drt != TREE_TYPE (res_var)) - res_var = build1 (CONVERT_EXPR, drt, res_var); - res_var = build (MODIFY_EXPR, drt, DECL_RESULT (method), res_var); - TREE_SIDE_EFFECTS (res_var) = 1; - } - } - else + /* Finally, do the return. */ + res_type = void_type_node; + if (res_var != NULL_TREE) { - /* This is necessary to get patch_return to run. */ - res_type = NULL_TREE; + tree drt; + if (! DECL_RESULT (method)) + abort (); + /* Make sure we copy the result variable to the actual + result. We use the type of the DECL_RESULT because it + might be different from the return type of the function: + it might be promoted. */ + drt = TREE_TYPE (DECL_RESULT (method)); + if (drt != TREE_TYPE (res_var)) + res_var = build1 (CONVERT_EXPR, drt, res_var); + res_var = build (MODIFY_EXPR, drt, DECL_RESULT (method), res_var); + TREE_SIDE_EFFECTS (res_var) = 1; } + body = build (COMPOUND_EXPR, void_type_node, body, build1 (RETURN_EXPR, res_type, res_var)); TREE_SIDE_EFFECTS (body) = 1; - - BLOCK_EXPR_BODY (block) = body; - return block; + + bind = build (BIND_EXPR, void_type_node, BLOCK_VARS (block), + body, block); + return bind; } /* Expand an operation to extract from or store into a field. @@ -2360,12 +2405,13 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index) { if (DECL_CONTEXT (field_decl) != current_class) error ("%Jassignment to final field '%D' not in field's class", - field_decl, field_decl); + field_decl, field_decl); else if (FIELD_STATIC (field_decl)) { if (!DECL_CLINIT_P (current_function_decl)) warning ("%Jassignment to final static field `%D' not in " - "class initializer", field_decl, field_decl); + "class initializer", + field_decl, field_decl); } else { @@ -2376,7 +2422,8 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index) field_decl, field_decl); } } - expand_assignment (field_ref, new_value, 0); + java_add_stmt (build (MODIFY_EXPR, + TREE_TYPE (field_ref), field_ref, new_value)); } else push_value (field_ref); @@ -2437,8 +2484,27 @@ java_expand_expr (tree exp, rtx target, enum machine_mode tmode, { tree current; + abort (); + switch (TREE_CODE (exp)) { + + case EXPR_WITH_FILE_LOCATION: + { + rtx to_return; + const char *saved_input_filename = input_filename; + int saved_lineno = input_line; + input_filename = EXPR_WFL_FILENAME (exp); + input_line = EXPR_WFL_LINENO (exp); + if (EXPR_WFL_EMIT_LINE_NOTE (exp)) + emit_line_note (input_location); + /* Possibly avoid switching back and forth here. */ + to_return = expand_expr (EXPR_WFL_NODE (exp), target, tmode, modifier); + input_filename = saved_input_filename; + input_line = saved_lineno; + return to_return; + } + case NEW_ARRAY_INIT: { rtx tmp; @@ -2576,12 +2642,6 @@ java_expand_expr (tree exp, rtx target, enum machine_mode tmode, build_decl (LABEL_DECL, NULL_TREE, NULL_TREE), NULL); return const0_rtx; - case SWITCH_EXPR: - expand_start_case (0, TREE_OPERAND (exp, 0), int_type_node, "switch"); - expand_expr_stmt (TREE_OPERAND (exp, 1)); - expand_end_case (TREE_OPERAND (exp, 0)); - return const0_rtx; - case TRY_EXPR: /* We expand a try[-catch] block */ @@ -2609,11 +2669,6 @@ java_expand_expr (tree exp, rtx target, enum machine_mode tmode, return expand_expr (build_exception_object_ref (TREE_TYPE (exp)), target, tmode, modifier); - case LABEL_EXPR: - /* Used only by expanded inline functions. */ - expand_label (TREE_OPERAND (exp, 0)); - return const0_rtx; - default: internal_error ("can't expand %s", tree_code_name [TREE_CODE (exp)]); } @@ -2799,7 +2854,7 @@ expand_byte_code (JCF *jcf, tree method) if (! verify_jvm_instructions (jcf, byte_ops, length)) return; - /* Translate bytecodes to rtl instructions. */ + /* Translate bytecodes. */ linenumber_pointer = linenumber_table; for (PC = 0; PC < length;) { @@ -2808,7 +2863,7 @@ expand_byte_code (JCF *jcf, tree method) tree label = lookup_label (PC); flush_quick_stack (); if ((instruction_bits [PC] & BCODE_TARGET) != 0) - expand_label (label); + java_add_stmt (build (LABEL_EXPR, void_type_node, label)); if (LABEL_VERIFIED (label) || PC == 0) load_type_state (label); } @@ -2855,8 +2910,7 @@ expand_byte_code (JCF *jcf, tree method) linenumber_pointer += 4; if (pc == PC) { - input_line = GET_u2 (linenumber_pointer - 2); - emit_line_note (input_location); + input_location.line = GET_u2 (linenumber_pointer - 2); if (!(instruction_bits[PC] & BCODE_HAS_MULTI_LINENUMBERS)) break; } @@ -2886,7 +2940,7 @@ java_push_constant_from_pool (JCF *jcf, int index) name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); index = alloc_name_constant (CONSTANT_String, name); c = build_ref_from_constant_pool (index); - TREE_TYPE (c) = promote_type (string_type_node); + c = convert (promote_type (string_type_node), c); } else c = get_constant (jcf, index); @@ -2905,7 +2959,7 @@ process_jvm_instruction (int PC, const unsigned char* byte_ops, if (instruction_bits [PC] & BCODE_EXCEPTION_TARGET) { tree type = pop_type (ptr_type_node); - push_value (build (JAVA_EXC_OBJ_EXPR, type)); + push_value (build_exception_object_ref (type)); } switch (byte_ops[PC++]) @@ -3007,46 +3061,24 @@ process_jvm_instruction (int PC, const unsigned char* byte_ops, #define LOOKUP_SWITCH \ { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \ tree selector = pop_value (INT_type_node); \ - tree duplicate, label; \ - tree type = TREE_TYPE (selector); \ - flush_quick_stack (); \ - expand_start_case (0, selector, type, "switch statement");\ + tree switch_expr = expand_java_switch (selector, oldpc + default_offset); \ while (--npairs >= 0) \ { \ jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \ - tree value = build_int_2 (match, match < 0 ? -1 : 0); \ - TREE_TYPE (value) = type; \ - label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \ - pushcase (value, convert, label, &duplicate); \ - expand_java_goto (oldpc + offset); \ + expand_java_add_case (switch_expr, match, oldpc + offset); \ } \ - label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \ - pushcase (NULL_TREE, 0, label, &duplicate); \ - expand_java_goto (oldpc + default_offset); \ - expand_end_case (selector); \ } #define TABLE_SWITCH \ { jint default_offset = IMMEDIATE_s4; \ jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \ tree selector = pop_value (INT_type_node); \ - tree duplicate, label; \ - tree type = TREE_TYPE (selector); \ - flush_quick_stack (); \ - expand_start_case (0, selector, type, "switch statement");\ + tree switch_expr = expand_java_switch (selector, oldpc + default_offset); \ for (; low <= high; low++) \ { \ jint offset = IMMEDIATE_s4; \ - tree value = build_int_2 (low, low < 0 ? -1 : 0); \ - TREE_TYPE (value) = type; \ - label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \ - pushcase (value, convert, label, &duplicate); \ - expand_java_goto (oldpc + offset); \ + expand_java_add_case (switch_expr, low, oldpc + offset); \ } \ - label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \ - pushcase (NULL_TREE, 0, label, &duplicate); \ - expand_java_goto (oldpc + default_offset); \ - expand_end_case (selector); \ } #define INVOKE(MAYBE_STATIC, IS_INTERFACE) \ @@ -3111,16 +3143,17 @@ process_jvm_instruction (int PC, const unsigned char* byte_ops, /* internal macro added for use by the WIDE case Added TREE_TYPE (decl) assignment, apbianco */ -#define STORE_INTERNAL(OPTYPE, OPVALUE) \ - { \ - tree decl, value; \ - int var = OPVALUE; \ - tree type = OPTYPE; \ - value = pop_value (type); \ - type = TREE_TYPE (value); \ - decl = find_local_variable (var, type, oldpc); \ - set_local_type (var, type ); \ - expand_assignment (decl, value, 0); \ +#define STORE_INTERNAL(OPTYPE, OPVALUE) \ + { \ + tree decl, value; \ + int index = OPVALUE; \ + tree type = OPTYPE; \ + value = pop_value (type); \ + type = TREE_TYPE (value); \ + decl = find_local_variable (index, type, oldpc); \ + set_local_type (index, type); \ + java_add_stmt (build (MODIFY_EXPR, type, decl, value)); \ + update_aliases (decl, index); \ } #define STORE(OPERAND_TYPE, OPERAND_VALUE) \ @@ -3143,7 +3176,7 @@ process_jvm_instruction (int PC, const unsigned char* byte_ops, flush_quick_stack (); \ c = build_java_monitor (call, o); \ TREE_SIDE_EFFECTS (c) = 1; \ - expand_expr_stmt (c); \ + java_add_stmt (c); \ } #define SPECIAL_IINC(IGNORED) \ @@ -3388,7 +3421,9 @@ force_evaluation_order (tree node) if (cmp) { - cmp = save_expr (build (COMPOUND_EXPR, TREE_TYPE (node), cmp, node)); + cmp = build (COMPOUND_EXPR, TREE_TYPE (node), cmp, node); + if (TREE_TYPE (cmp) != void_type_node) + cmp = save_expr (cmp); CAN_COMPLETE_NORMALLY (cmp) = CAN_COMPLETE_NORMALLY (node); TREE_SIDE_EFFECTS (cmp) = 1; node = cmp; @@ -3429,5 +3464,46 @@ emit_init_test_initialization (void **entry, void *x ATTRIBUTE_UNUSED) return true; } -#include "gt-java-expr.h" +/* EXPR_WITH_FILE_LOCATION are used to keep track of the exact + location where an expression or an identifier were encountered. It + is necessary for languages where the frontend parser will handle + recursively more than one file (Java is one of them). */ +tree +build_expr_wfl (tree node, const char *file, int line, int col) +{ + static const char *last_file = 0; + static tree last_filenode = NULL_TREE; + tree wfl = make_node (EXPR_WITH_FILE_LOCATION); + + EXPR_WFL_NODE (wfl) = node; + EXPR_WFL_SET_LINECOL (wfl, line, col); + if (file != last_file) + { + last_file = file; + last_filenode = file ? get_identifier (file) : NULL_TREE; + } + + EXPR_WFL_FILENAME_NODE (wfl) = last_filenode; + if (node) + { + if (IS_NON_TYPE_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (node)))) + TREE_SIDE_EFFECTS (wfl) = TREE_SIDE_EFFECTS (node); + TREE_TYPE (wfl) = TREE_TYPE (node); + } + + return wfl; +} + + +/* Build a node to represent empty statements and blocks. */ + +tree +build_java_empty_stmt (void) +{ + tree t = build_empty_stmt (); + CAN_COMPLETE_NORMALLY (t) = 1; + return t; +} + +#include "gt-java-expr.h" diff --git a/gcc/java/java-except.h b/gcc/java/java-except.h index b536ce0..0646d61 100644 --- a/gcc/java/java-except.h +++ b/gcc/java/java-except.h @@ -50,6 +50,9 @@ struct eh_range /* True if this range has already been expanded. */ int expanded; + + /* The TRY_CATCH_EXPR for this EH range. */ + tree stmt; }; /* A dummy range that represents the entire method. */ diff --git a/gcc/java/java-gimplify.c b/gcc/java/java-gimplify.c new file mode 100644 index 0000000..ae8acd5 --- /dev/null +++ b/gcc/java/java-gimplify.c @@ -0,0 +1,277 @@ +/* Java(TM) language-specific gimplification routines. + + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. + +Java and all Java-based marks are trademarks or registered trademarks +of Sun Microsystems, Inc. in the United States and other countries. +The Free Software Foundation is independent of Sun Microsystems, Inc. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "java-tree.h" +#include "tree-dump.h" +#include "tree-simple.h" +#include "toplev.h" + +static tree java_gimplify_case_expr (tree); +static tree java_gimplify_default_expr (tree); +static tree java_gimplify_block (tree); +static tree java_gimplify_new_array_init (tree); +static tree java_gimplify_try_expr (tree); + +static void dump_java_tree (enum tree_dump_index, tree); + +/* Convert a Java tree to GENERIC. */ + +void +java_genericize (tree fndecl) +{ + dump_java_tree (TDI_original, fndecl); + + /* Genericize with the gimplifier. */ + gimplify_function_tree (fndecl); + + dump_function (TDI_generic, fndecl); +} + +/* Gimplify a Java tree. */ + +int +java_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED, + tree *post_p ATTRIBUTE_UNUSED) +{ + char code_class = TREE_CODE_CLASS(TREE_CODE (*expr_p)); + + /* Java insists on strict left-to-right evaluation of expressions. + A problem may arise if a variable used in the lhs of a binary + operation is altered by an assignment to that value in the rhs + before we've performed the operation. So, we always copy every + LHS to a temprorary variable. + + FIXME: Are there any other cases where we should do this? + Parameter lists, maybe? Or perhaps that's unnecessary because + the front end already generates SAVE_EXPRs. */ + if (code_class == '2') + { + tree lhs = TREE_OPERAND (*expr_p, 0); + enum gimplify_status stat + = gimplify_expr (&lhs, pre_p, post_p, is_gimple_tmp_var, fb_rvalue); + if (stat == GS_ERROR) + return stat; + TREE_OPERAND (*expr_p, 0) = lhs; + } + + switch (TREE_CODE (*expr_p)) + { + case BLOCK: + *expr_p = java_gimplify_block (*expr_p); + break; + + case EXPR_WITH_FILE_LOCATION: + input_location.file = EXPR_WFL_FILENAME (*expr_p); + input_location.line = EXPR_WFL_LINENO (*expr_p); + *expr_p = EXPR_WFL_NODE (*expr_p); + annotate_with_locus (*expr_p, input_location); + break; + + case CASE_EXPR: + *expr_p = java_gimplify_case_expr (*expr_p); + break; + + case DEFAULT_EXPR: + *expr_p = java_gimplify_default_expr (*expr_p); + break; + + case NEW_ARRAY_INIT: + *expr_p = java_gimplify_new_array_init (*expr_p); + break; + + case TRY_EXPR: + *expr_p = java_gimplify_try_expr (*expr_p); + break; + + case JAVA_CATCH_EXPR: + *expr_p = TREE_OPERAND (*expr_p, 0); + break; + + case JAVA_EXC_OBJ_EXPR: + *expr_p = build_exception_object_ref (TREE_TYPE (*expr_p)); + break; + + /* These should already be lowered before we get here. */ + case URSHIFT_EXPR: + case COMPARE_EXPR: + case COMPARE_L_EXPR: + case COMPARE_G_EXPR: + case UNARY_PLUS_EXPR: + case NEW_ARRAY_EXPR: + case NEW_ANONYMOUS_ARRAY_EXPR: + case NEW_CLASS_EXPR: + case THIS_EXPR: + case SYNCHRONIZED_EXPR: + case CONDITIONAL_EXPR: + case INSTANCEOF_EXPR: + case CLASS_LITERAL: + abort (); + + default: + return GS_UNHANDLED; + } + + return GS_OK; +} + +static tree +java_gimplify_case_expr (tree expr) +{ + tree label = create_artificial_label (); + return build (CASE_LABEL_EXPR, void_type_node, + TREE_OPERAND (expr, 0), NULL_TREE, label); +} + +static tree +java_gimplify_default_expr (tree expr ATTRIBUTE_UNUSED) +{ + tree label = create_artificial_label (); + return build (CASE_LABEL_EXPR, void_type_node, NULL_TREE, NULL_TREE, label); +} + +/* Gimplify BLOCK into a BIND_EXPR. */ + +static tree +java_gimplify_block (tree java_block) +{ + tree decls = BLOCK_VARS (java_block); + tree body = BLOCK_EXPR_BODY (java_block); + tree outer = gimple_current_bind_expr (); + tree block; + + /* Don't bother with empty blocks. */ + if (! body) + return build_empty_stmt (); + + if (IS_EMPTY_STMT (body)) + return body; + + /* Make a proper block. Java blocks are unsuitable for BIND_EXPR + because they use BLOCK_SUBBLOCKS for another purpose. */ + block = make_node (BLOCK); + BLOCK_VARS (block) = decls; + if (outer != NULL_TREE) + { + outer = BIND_EXPR_BLOCK (outer); + BLOCK_SUBBLOCKS (outer) = chainon (BLOCK_SUBBLOCKS (outer), block); + } + + return build (BIND_EXPR, TREE_TYPE (java_block), decls, body, block); +} + +/* Gimplify a NEW_ARRAY_INIT node into array/element assignments. */ + +static tree +java_gimplify_new_array_init (tree exp) +{ + tree array_type = TREE_TYPE (TREE_TYPE (exp)); + tree data_field = lookup_field (&array_type, get_identifier ("data")); + tree element_type = TYPE_ARRAY_ELEMENT (array_type); + HOST_WIDE_INT ilength = java_array_type_length (array_type); + tree length = build_int_2 (ilength, 0); + tree init = TREE_OPERAND (exp, 0); + tree values = CONSTRUCTOR_ELTS (init); + + tree array_ptr_type = build_pointer_type (array_type); + tree block = build (BLOCK, array_ptr_type); + tree tmp = build_decl (VAR_DECL, get_identifier ("<tmp>"), array_ptr_type); + tree array = build_decl (VAR_DECL, get_identifier ("<array>"), array_ptr_type); + tree body = build (MODIFY_EXPR, array_ptr_type, tmp, + build_new_array (element_type, length)); + + int index = 0; + + DECL_CONTEXT (array) = current_function_decl; + DECL_CONTEXT (tmp) = current_function_decl; + + /* FIXME: try to allocate array statically? */ + while (values != NULL_TREE) + { + /* FIXME: Should use build_java_arrayaccess here, but avoid + bounds checking. */ + tree lhs = build (COMPONENT_REF, TREE_TYPE (data_field), + build_java_indirect_ref (array_type, tmp, 0), + data_field); + tree assignment = build (MODIFY_EXPR, element_type, + build (ARRAY_REF, element_type, lhs, + build_int_2 (index++, 0)), + TREE_VALUE (values)); + body = build (COMPOUND_EXPR, element_type, body, assignment); + values = TREE_CHAIN (values); + } + + body = build (COMPOUND_EXPR, array_ptr_type, body, + build (MODIFY_EXPR, array_ptr_type, array, tmp)); + TREE_CHAIN (tmp) = array; + BLOCK_VARS (block) = tmp; + BLOCK_EXPR_BODY (block) = body; + return java_gimplify_block (block); +} + +static tree +java_gimplify_try_expr (tree try_expr) +{ + tree body = TREE_OPERAND (try_expr, 0); + tree handler = TREE_OPERAND (try_expr, 1); + tree catch = NULL_TREE; + + /* Build a CATCH_EXPR for each handler. */ + while (handler) + { + tree java_catch = TREE_OPERAND (handler, 0); + tree catch_type = TREE_TYPE (TREE_TYPE (BLOCK_EXPR_DECLS (java_catch))); + tree expr = build (CATCH_EXPR, void_type_node, + prepare_eh_table_type (catch_type), + handler); + if (catch) + catch = build (COMPOUND_EXPR, void_type_node, catch, expr); + else + catch = expr; + handler = TREE_CHAIN (handler); + } + return build (TRY_CATCH_EXPR, void_type_node, body, catch); +} + +/* Dump a tree of some kind. This is a convenience wrapper for the + dump_* functions in tree-dump.c. */ +static void +dump_java_tree (enum tree_dump_index phase, tree t) +{ + FILE *stream; + int flags; + + stream = dump_begin (phase, &flags); + flags |= TDF_SLIM; + if (stream) + { + dump_node (t, flags, stream); + dump_end (phase, stream); + } +} diff --git a/gcc/java/java-tree.def b/gcc/java/java-tree.def index f15bc38..25ee538 100644 --- a/gcc/java/java-tree.def +++ b/gcc/java/java-tree.def @@ -55,7 +55,7 @@ DEFTREECODE (TRY_EXPR, "try-catch", 'e', 2) /* Catch clause. Operand 0 is the catch clause block, which contains the declaration of the catch clause parameter. */ -DEFTREECODE (CATCH_EXPR, "catch", '1', 1) +DEFTREECODE (JAVA_CATCH_EXPR, "catch", '1', 1) /* Synchronized statement. Operand 0 is the expression on which we wish to synchronize, @@ -91,6 +91,13 @@ DEFTREECODE (CLASS_LITERAL, "class_literal", '1', 1) /* The Java object within the exception object from the runtime. */ DEFTREECODE (JAVA_EXC_OBJ_EXPR, "java_exc_obj_expr", 'e', 0) +/* Annotates a tree node (usually an expression) with source location + information: a file name (EXPR_WFL_FILENAME); a line number + (EXPR_WFL_LINENO); and column number (EXPR_WFL_COLNO). It is + expanded as the contained node (EXPR_WFL_NODE); a line note should + be emitted first if EXPR_WFL_EMIT_LINE_NOTE. */ +DEFTREECODE (EXPR_WITH_FILE_LOCATION, "expr_with_file_location", 'e', 3) + /* Local variables: mode:c diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index faad727..b04ee4b 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -349,7 +349,6 @@ enum java_tree_index JTI_DOUBLE_ZERO_NODE, JTI_INTEGER_TWO_NODE, JTI_INTEGER_FOUR_NODE, - JTI_EMPTY_STMT_NODE, JTI_METHODTABLE_TYPE, JTI_METHODTABLE_PTR_TYPE, @@ -562,8 +561,6 @@ extern GTY(()) tree java_global_trees[JTI_MAX]; java_global_trees[JTI_INTEGER_TWO_NODE] #define integer_four_node \ java_global_trees[JTI_INTEGER_FOUR_NODE] -#define empty_stmt_node \ - java_global_trees[JTI_EMPTY_STMT_NODE] /* The type for struct methodtable. */ #define methodtable_type \ @@ -1178,6 +1175,7 @@ extern void set_java_signature (tree, tree); extern tree build_static_field_ref (tree); extern tree build_address_of (tree); extern tree find_local_variable (int index, tree type, int pc); +extern void update_aliases (tree decl, int index); extern tree find_stack_slot (int index, tree type); extern tree build_prim_array_type (tree, HOST_WIDE_INT); extern tree build_java_array_type (tree, HOST_WIDE_INT); @@ -1235,7 +1233,6 @@ extern int interface_of_p (tree, tree); extern int inherits_from_p (tree, tree); extern int common_enclosing_context_p (tree, tree); extern int enclosing_context_p (tree, tree); -extern void complete_start_java_method (tree); extern tree build_result_decl (tree); extern void emit_handlers (void); extern void set_method_index (tree decl, tree method_index); @@ -1341,8 +1338,13 @@ extern void compile_resource_data (const char *name, const char *buffer, int); extern void compile_resource_file (const char *, const char *); extern void write_resource_constructor (void); extern void init_resource_processing (void); +extern tree build_java_empty_stmt (void); +extern tree add_stmt_to_compound (tree, tree, tree); +extern tree java_add_stmt (tree); +extern tree java_add_local_var (tree decl); +extern tree *get_stmts (void); -extern void start_complete_expand_method (tree); +extern void finish_method (tree); extern void java_expand_body (tree); extern int get_symbol_table_index (tree, tree *); @@ -1819,4 +1821,28 @@ enum }; #undef DEBUG_JAVA_BINDING_LEVELS + +/* In an EXPR_WITH_FILE_LOCATION node. */ +#define EXPR_WFL_EMIT_LINE_NOTE(NODE) \ + (EXPR_WITH_FILE_LOCATION_CHECK (NODE)->common.public_flag) +#undef EXPR_WFL_NODE +#define EXPR_WFL_NODE(NODE) \ + TREE_OPERAND (EXPR_WITH_FILE_LOCATION_CHECK (NODE), 0) +#undef EXPR_WFL_FILENAME_NODE +#define EXPR_WFL_FILENAME_NODE(NODE) \ + TREE_OPERAND (EXPR_WITH_FILE_LOCATION_CHECK (NODE), 1) +#define EXPR_WFL_FILENAME(NODE) \ + IDENTIFIER_POINTER (EXPR_WFL_FILENAME_NODE (NODE)) +/* ??? Java uses this in all expressions. */ +#define EXPR_WFL_LINECOL(NODE) (EXPR_CHECK (NODE)->exp.complexity) +#define EXPR_WFL_LINENO(NODE) (EXPR_WFL_LINECOL (NODE) >> 12) +#define EXPR_WFL_COLNO(NODE) (EXPR_WFL_LINECOL (NODE) & 0xfff) +#define EXPR_WFL_SET_LINECOL(NODE, LINE, COL) \ + (EXPR_WFL_LINECOL(NODE) = ((LINE) << 12) | ((COL) & 0xfff)) + +extern tree build_expr_wfl PARAMS ((tree, const char *, int, int)); + +extern void java_genericize PARAMS ((tree)); +extern int java_gimplify_expr PARAMS ((tree *, tree *, tree *)); + #endif /* ! GCC_JAVA_TREE_H */ diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c index e8fd413..a44e860 100644 --- a/gcc/java/jcf-parse.c +++ b/gcc/java/jcf-parse.c @@ -738,7 +738,7 @@ parse_class_file (void) DECL_MAX_LOCALS (method) = decl_max_locals; start_java_method (method); give_name_to_locals (jcf); - expand_expr_stmt (build_jni_stub (method)); + *get_stmts () = build_jni_stub (method); end_java_method (); continue; } @@ -762,7 +762,7 @@ parse_class_file (void) for (ptr += 2; --i >= 0; ptr += 4) { int line = GET_u2 (ptr); - /* Set initial lineno lineno to smallest linenumber. + /* Set initial input_line to smallest linenumber. * Needs to be set before init_function_start. */ if (input_line == 0 || line < input_line) input_line = line; @@ -780,7 +780,7 @@ parse_class_file (void) give_name_to_locals (jcf); - /* Actually generate code. */ + /* Convert bytecode to trees. */ expand_byte_code (jcf, method); end_java_method (); @@ -1111,13 +1111,16 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED) java_expand_classes (); if (!java_report_errors () && !flag_syntax_only) { - /* Optimize and expand all classes compiled from source. */ - cgraph_finalize_compilation_unit (); - cgraph_optimize (); + /* Expand all classes compiled from source. */ java_finish_classes (); /* Emit the .jcf section. */ emit_register_classes (); + + /* Only finalize the compilation unit after we've told cgraph which + functions have their addresses stored. */ + cgraph_finalize_compilation_unit (); + cgraph_optimize (); } write_resource_constructor (); diff --git a/gcc/java/jcf-write.c b/gcc/java/jcf-write.c index 36a21d3..c715a2c 100644 --- a/gcc/java/jcf-write.c +++ b/gcc/java/jcf-write.c @@ -1428,7 +1428,7 @@ generate_bytecode_insns (tree exp, int target, struct jcf_partial *state) { location_t saved_location = input_location; tree body = EXPR_WFL_NODE (exp); - if (body == empty_stmt_node) + if (IS_EMPTY_STMT (body)) break; input_filename = EXPR_WFL_FILENAME (exp); input_line = EXPR_WFL_LINENO (exp); @@ -1773,7 +1773,7 @@ generate_bytecode_insns (tree exp, int target, struct jcf_partial *state) case RETURN_EXPR: exp = TREE_OPERAND (exp, 0); if (exp == NULL_TREE) - exp = empty_stmt_node; + exp = build_java_empty_stmt (); else if (TREE_CODE (exp) != MODIFY_EXPR) abort (); else diff --git a/gcc/java/lang.c b/gcc/java/lang.c index 4856e5f..20f13e5 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -66,8 +66,6 @@ static bool java_can_use_bit_fields_p (void); static bool java_dump_tree (void *, tree); static void dump_compound_expr (dump_info_p, tree); static bool java_decl_ok_for_sibcall (tree); -static int java_estimate_num_insns (tree); -static int java_start_inlining (tree); static tree java_get_callee_fndecl (tree); #ifndef TARGET_OBJECT_SUFFIX @@ -174,7 +172,8 @@ int flag_force_classes_archive_check; /* When zero, don't optimize static class initialization. This flag shouldn't be tested alone, use STATIC_CLASS_INITIALIZATION_OPTIMIZATION_P instead. */ -int flag_optimize_sci = 1; +/* FIXME: Make this work with gimplify. */ +int flag_optimize_sci = 0; /* When nonzero, use offset tables for virtual method calls in order to improve binary compatibility. */ @@ -249,18 +248,15 @@ struct language_function GTY(()) #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE #define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE java_signed_or_unsigned_type -#undef LANG_HOOKS_TREE_INLINING_WALK_SUBTREES -#define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES java_tree_inlining_walk_subtrees - -#undef LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS -#define LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS java_estimate_num_insns - -#undef LANG_HOOKS_TREE_INLINING_START_INLINING -#define LANG_HOOKS_TREE_INLINING_START_INLINING java_start_inlining - #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN java_dump_tree +#undef LANG_HOOKS_GIMPLIFY_EXPR +#define LANG_HOOKS_GIMPLIFY_EXPR java_gimplify_expr + +#undef LANG_HOOKS_TREE_INLINING_WALK_SUBTREES +#define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES java_tree_inlining_walk_subtrees + #undef LANG_HOOKS_DECL_OK_FOR_SIBCALL #define LANG_HOOKS_DECL_OK_FOR_SIBCALL java_decl_ok_for_sibcall @@ -732,17 +728,13 @@ java_post_options (const char **pfilename) { const char *filename = *pfilename; - /* Use tree inlining if possible. Function instrumentation is only - done in the RTL level, so we disable tree inlining. */ - if (! flag_instrument_function_entry_exit) + /* Use tree inlining. */ + if (!flag_no_inline) + flag_no_inline = 1; + if (flag_inline_functions) { - if (!flag_no_inline) - flag_no_inline = 1; - if (flag_inline_functions) - { - flag_inline_trees = 2; - flag_inline_functions = 0; - } + flag_inline_trees = 2; + flag_inline_functions = 0; } /* Open input file. */ @@ -1124,122 +1116,6 @@ java_decl_ok_for_sibcall (tree decl) return decl != NULL && DECL_CONTEXT (decl) == output_class; } -/* Used by estimate_num_insns. Estimate number of instructions seen - by given statement. */ -static tree -java_estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data) -{ - int *count = data; - tree x = *tp; - - if (TYPE_P (x) || DECL_P (x)) - { - *walk_subtrees = 0; - return NULL; - } - /* Assume that constants and references counts nothing. These should - be majorized by amount of operations among them we count later - and are common target of CSE and similar optimizations. */ - if (TREE_CODE_CLASS (TREE_CODE (x)) == 'c' - || TREE_CODE_CLASS (TREE_CODE (x)) == 'r') - return NULL; - switch (TREE_CODE (x)) - { - /* Recognize assignments of large structures and constructors of - big arrays. */ - case MODIFY_EXPR: - case CONSTRUCTOR: - { - HOST_WIDE_INT size; - - size = int_size_in_bytes (TREE_TYPE (x)); - - if (size < 0 || size > MOVE_MAX_PIECES * MOVE_RATIO) - *count += 10; - else - *count += ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES); - } - break; - /* Few special cases of expensive operations. This is usefull - to avoid inlining on functions having too many of these. */ - case TRUNC_DIV_EXPR: - case CEIL_DIV_EXPR: - case FLOOR_DIV_EXPR: - case ROUND_DIV_EXPR: - case TRUNC_MOD_EXPR: - case CEIL_MOD_EXPR: - case FLOOR_MOD_EXPR: - case ROUND_MOD_EXPR: - case RDIV_EXPR: - case CALL_EXPR: - - case NEW_ARRAY_EXPR: - case NEW_ANONYMOUS_ARRAY_EXPR: - case NEW_CLASS_EXPR: - *count += 10; - break; - /* Various containers that will produce no code themselves. */ - case INIT_EXPR: - case TARGET_EXPR: - case BIND_EXPR: - case BLOCK: - case TREE_LIST: - case TREE_VEC: - case IDENTIFIER_NODE: - case PLACEHOLDER_EXPR: - case WITH_CLEANUP_EXPR: - case CLEANUP_POINT_EXPR: - case NOP_EXPR: - case VIEW_CONVERT_EXPR: - case SAVE_EXPR: - case UNSAVE_EXPR: - case COMPLEX_EXPR: - case REALPART_EXPR: - case IMAGPART_EXPR: - case TRY_CATCH_EXPR: - case TRY_FINALLY_EXPR: - case LABEL_EXPR: - case EXIT_EXPR: - case LABELED_BLOCK_EXPR: - case EXIT_BLOCK_EXPR: - case EXPR_WITH_FILE_LOCATION: - case UNARY_PLUS_EXPR: - case THIS_EXPR: - case DEFAULT_EXPR: - case TRY_EXPR: - - break; - case CLASS_LITERAL: - *walk_subtrees = 0; - break; - default: - (*count)++; - } - return NULL; -} - -/* Estimate number of instructions that will be created by expanding the body. */ -static int -java_estimate_num_insns (tree decl) -{ - int num = 0; - walk_tree_without_duplicates (&DECL_SAVED_TREE (decl), - java_estimate_num_insns_1, &num); - return num; -} - -/* Start inlining fn. Called by the tree inliner via - lang_hooks.tree_inlining.cannot_inline_tree_fn. */ - -static int -java_start_inlining (tree fn) -{ - /* A java function's body doesn't have a BLOCK structure suitable - for debug output until it is expanded. Prevent inlining functions - that are not yet expanded. */ - return TREE_ASM_WRITTEN (fn) ? 1 : 0; -} - /* Given a call_expr, try to figure out what its target might be. In the case of an indirection via the atable, search for the decl. If the decl is external, we return NULL. If we don't, the optimizer diff --git a/gcc/java/lang.opt b/gcc/java/lang.opt index 3e9cdf1..ae367a7 100644 --- a/gcc/java/lang.opt +++ b/gcc/java/lang.opt @@ -116,9 +116,6 @@ Java JoinedOrMissing RejectNegative fcompile-resource= Java Joined RejectNegative -fdump- -Java Joined RejectNegative - femit-class-file Java diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 3212dda..d6c597f 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -144,6 +144,7 @@ static tree java_complete_tree (tree); static tree maybe_generate_pre_expand_clinit (tree); static int analyze_clinit_body (tree, tree); static int maybe_yank_clinit (tree); +static void start_complete_expand_method (tree); static void java_complete_expand_method (tree); static void java_expand_method_bodies (tree); static int unresolved_type_p (tree, tree *); @@ -197,7 +198,6 @@ static void check_deprecation (tree, tree); static int class_in_current_package (tree); static tree build_if_else_statement (int, tree, tree, tree); static tree patch_if_else_statement (tree); -static tree add_stmt_to_compound (tree, tree, tree); static tree add_stmt_to_block (tree, tree, tree); static tree patch_exit_expr (tree); static tree build_labeled_block (int, tree); @@ -910,7 +910,7 @@ class_body_declaration: | constructor_declaration | block /* Added, JDK1.1, instance initializer */ { - if ($1 != empty_stmt_node) + if (!IS_EMPTY_STMT ($1)) { TREE_CHAIN ($1) = CPC_INSTANCE_INITIALIZER_STMT (ctxp); SET_CPC_INSTANCE_INITIALIZER_STMT (ctxp, $1); @@ -1198,7 +1198,7 @@ constructor_body: addition (super invocation and field initialization) */ block_begin constructor_block_end { - BLOCK_EXPR_BODY ($2) = empty_stmt_node; + BLOCK_EXPR_BODY ($2) = build_java_empty_stmt (); $$ = $2; } | block_begin explicit_constructor_invocation constructor_block_end @@ -1376,7 +1376,7 @@ block_end: EXPR_WFL_ADD_COL ($1.location, 1); $$ = exit_block (); if (!BLOCK_SUBBLOCKS ($$)) - BLOCK_SUBBLOCKS ($$) = empty_stmt_node; + BLOCK_SUBBLOCKS ($$) = build_java_empty_stmt (); } ; @@ -1455,7 +1455,7 @@ empty_statement: EXPR_WFL_SET_LINECOL (wfl_operator, input_line, -1); parse_warning_context (wfl_operator, "An empty declaration is a deprecated feature that should not be used"); } - $$ = empty_stmt_node; + $$ = build_java_empty_stmt (); } ; @@ -1588,7 +1588,7 @@ switch_statement: switch_expression: SWITCH_TK OP_TK expression CP_TK { - $$ = build (SWITCH_EXPR, NULL_TREE, $3, NULL_TREE); + $$ = build (SWITCH_EXPR, NULL_TREE, $3, NULL_TREE, NULL_TREE); EXPR_WFL_LINECOL ($$) = $2.location; } | SWITCH_TK error @@ -1698,7 +1698,7 @@ for_statement: $$ = finish_for_loop (0, NULL_TREE, $4, $6); /* We have not condition, so we get rid of the EXIT_EXPR */ LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) = - empty_stmt_node; + build_java_empty_stmt (); } | for_begin SC_TK error {yyerror ("Invalid control expression"); RECOVER;} @@ -1716,7 +1716,7 @@ for_statement_nsi: $$ = finish_for_loop (0, NULL_TREE, $4, $6); /* We have not condition, so we get rid of the EXIT_EXPR */ LOOP_EXPR_BODY_CONDITION_EXPR (LOOP_EXPR_BODY ($$), 0) = - empty_stmt_node; + build_java_empty_stmt (); } ; @@ -1747,7 +1747,7 @@ for_begin: } ; for_init: /* Can be empty */ - { $$ = empty_stmt_node; } + { $$ = build_java_empty_stmt (); } | statement_expression_list { /* Init statement recorded within the previously @@ -1765,7 +1765,7 @@ for_init: /* Can be empty */ ; for_update: /* Can be empty */ - {$$ = empty_stmt_node;} + {$$ = build_java_empty_stmt ();} | statement_expression_list { $$ = build_debugable_stmt (BUILD_LOCATION (), $1); } ; @@ -1918,7 +1918,7 @@ catch_clause_parameter: declare_local_variables (0, TREE_VALUE ($3), build_tree_list (TREE_PURPOSE ($3), init)); - $$ = build1 (CATCH_EXPR, NULL_TREE, ccpb); + $$ = build1 (JAVA_CATCH_EXPR, NULL_TREE, ccpb); EXPR_WFL_LINECOL ($$) = $1.location; } else @@ -2988,7 +2988,7 @@ parse_jdk1_1_error (const char *msg) { sorry (": `%s' JDK1.1(TM) feature", msg); java_error_count++; - return empty_stmt_node; + return build_java_empty_stmt (); } static int do_warning = 0; @@ -4339,7 +4339,7 @@ register_fields (int flags, tree type, tree variable_list) if (duplicate_declaration_error_p (current_name, real_type, cl)) continue; - /* Set lineno to the line the field was found and create a + /* Set input_line to the line the field was found and create a declaration for it. Eventually sets the @deprecated tag flag. */ if (flag_emit_xref) input_line = EXPR_WFL_LINECOL (cl); @@ -5491,7 +5491,7 @@ java_fix_constructors (void) } /* safe_layout_class just makes sure that we can load a class without - disrupting the current_class, input_file, lineno, etc, information + disrupting the current_class, input_file, input_line, etc, information about the class processed currently. */ void @@ -7047,7 +7047,7 @@ find_in_imports_on_demand (tree enclosing_type, tree class_type) if (! (node = maybe_get_identifier (id_name))) continue; - /* Setup lineno so that it refers to the line of the import (in + /* Setup input_line so that it refers to the line of the import (in case we parse a class file and encounter errors */ input_line = EXPR_WFL_LINENO (TREE_PURPOSE (import)); @@ -7527,19 +7527,17 @@ source_end_java_method (void) /* Turn function bodies with only a NOP expr null, so they don't get generated at all and we won't get warnings when using the -W -Wall flags. */ - if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) == empty_stmt_node) + if (IS_EMPTY_STMT (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)))) BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) = NULL_TREE; - /* We've generated all the trees for this function, and it has been - patched. Dump it to a file if the user requested it. */ - dump_java_tree (TDI_original, fndecl); - - /* Defer expanding the method until cgraph analysis is complete. */ - if (DECL_SAVED_TREE (fndecl)) - cgraph_finalize_function (fndecl, false); + if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) + && ! flag_emit_class_files + && ! flag_emit_xref) + finish_method (fndecl); current_function_decl = NULL_TREE; java_parser_context_restore_global (); + current_function_decl = NULL_TREE; } /* Record EXPR in the current function block. Complements compound @@ -7569,18 +7567,6 @@ add_stmt_to_block (tree b, tree type, tree stmt) return c; } -/* Add STMT to EXISTING if possible, otherwise create a new - COMPOUND_EXPR and add STMT to it. */ - -static tree -add_stmt_to_compound (tree existing, tree type, tree stmt) -{ - if (existing) - return build (COMPOUND_EXPR, type, existing, stmt); - else - return stmt; -} - void java_layout_seen_class_methods (void) { tree previous_list = all_class_list; @@ -7853,7 +7839,7 @@ maybe_generate_pre_expand_clinit (tree class_type) /* We build the assignment expression that will initialize the field to its value. There are strict rules on static initializers (8.5). FIXME */ - if (TREE_CODE (stmt) != BLOCK && stmt != empty_stmt_node) + if (TREE_CODE (stmt) != BLOCK && !IS_EMPTY_STMT (stmt)) stmt = build_debugable_stmt (EXPR_WFL_LINECOL (stmt), stmt); java_method_add_stmt (mdecl, stmt); } @@ -7947,7 +7933,7 @@ maybe_yank_clinit (tree mdecl) bbody = BLOCK_EXPR_BODY (bbody); else return 0; - if (bbody && ! flag_emit_class_files && bbody != empty_stmt_node) + if (bbody && ! flag_emit_class_files && !IS_EMPTY_STMT (bbody)) return 0; type = DECL_CONTEXT (mdecl); @@ -7981,7 +7967,7 @@ maybe_yank_clinit (tree mdecl) /* Now we analyze the method body and look for something that isn't a MODIFY_EXPR */ - if (bbody != empty_stmt_node && analyze_clinit_body (type, bbody)) + if (!IS_EMPTY_STMT (bbody) && analyze_clinit_body (type, bbody)) return 0; /* Get rid of <clinit> in the class' list of methods */ @@ -8146,7 +8132,6 @@ java_expand_method_bodies (tree class) for (decl = TYPE_METHODS (class); decl; decl = TREE_CHAIN (decl)) { tree block; - tree body; if (! DECL_FUNCTION_BODY (decl)) continue; @@ -8155,17 +8140,9 @@ java_expand_method_bodies (tree class) block = BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl)); - if (TREE_CODE (block) != BLOCK) - abort (); - - /* Save the function body for inlining. */ + /* Save the function body for gimplify and inlining. */ DECL_SAVED_TREE (decl) = block; - body = BLOCK_EXPR_BODY (block); - - if (TREE_TYPE (body) == NULL_TREE) - abort (); - /* It's time to assign the variable flagging static class initialization based on which classes invoked static methods are definitely initializing. This should be flagged. */ @@ -8197,41 +8174,7 @@ java_expand_method_bodies (tree class) } } - /* Prepend class initialization to static methods. */ - if (METHOD_STATIC (decl) && ! METHOD_PRIVATE (decl) - && ! flag_emit_class_files - && ! DECL_CLINIT_P (decl) - && ! CLASS_INTERFACE (TYPE_NAME (class))) - { - tree init = build (CALL_EXPR, void_type_node, - build_address_of (soft_initclass_node), - build_tree_list (NULL_TREE, - build_class_ref (class)), - NULL_TREE); - TREE_SIDE_EFFECTS (init) = 1; - body = build (COMPOUND_EXPR, TREE_TYPE (body), init, body); - BLOCK_EXPR_BODY (block) = body; - } - - /* Wrap synchronized method bodies in a monitorenter - plus monitorexit cleanup. */ - if (METHOD_SYNCHRONIZED (decl) && ! flag_emit_class_files) - { - tree enter, exit, lock; - if (METHOD_STATIC (decl)) - lock = build_class_ref (class); - else - lock = DECL_ARGUMENTS (decl); - BUILD_MONITOR_ENTER (enter, lock); - BUILD_MONITOR_EXIT (exit, lock); - - body = build (COMPOUND_EXPR, void_type_node, - enter, - build (TRY_FINALLY_EXPR, void_type_node, body, exit)); - BLOCK_EXPR_BODY (block) = body; - } - - /* Expand the the function body. */ + /* Expand the function body. */ source_end_java_method (); } } @@ -8963,7 +8906,7 @@ fix_constructors (tree mdecl) { compound = add_stmt_to_compound (compound, NULL_TREE, TREE_OPERAND (found_call, 0)); - TREE_OPERAND (found_call, 0) = empty_stmt_node; + TREE_OPERAND (found_call, 0) = build_java_empty_stmt (); } DECL_INIT_CALLS_THIS (mdecl) = invokes_this; @@ -9470,7 +9413,7 @@ resolve_field_access (tree qual_wfl, tree *field_decl, tree *field_type) { int is_static = 0; tree field_ref; - tree decl, where_found, type_found; + tree decl = NULL_TREE, where_found, type_found; if (resolve_qualified_expression_name (qual_wfl, &decl, &where_found, &type_found)) @@ -10915,10 +10858,10 @@ patch_invoke (tree patch, tree method, tree args) /* We have to call force_evaluation_order now because creating a COMPOUND_EXPR wraps the arg list in a way that makes it unrecognizable by force_evaluation_order later. Yuk. */ - tree save = save_expr (force_evaluation_order (patch)); + tree save = force_evaluation_order (patch); tree type = TREE_TYPE (patch); - patch = build (COMPOUND_EXPR, type, save, empty_stmt_node); + patch = build (COMPOUND_EXPR, type, save, build_java_empty_stmt ()); list = tree_cons (method, patch, DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl)); @@ -11547,12 +11490,12 @@ java_complete_lhs (tree node) long blocks. */ ptr = &BLOCK_EXPR_BODY (node); while (TREE_CODE (*ptr) == COMPOUND_EXPR - && TREE_OPERAND (*ptr, 1) != empty_stmt_node) + && !IS_EMPTY_STMT (TREE_OPERAND (*ptr, 1))) { tree cur = java_complete_tree (TREE_OPERAND (*ptr, 0)); tree *next = &TREE_OPERAND (*ptr, 1); TREE_OPERAND (*ptr, 0) = cur; - if (cur == empty_stmt_node) + if (IS_EMPTY_STMT (cur)) { /* Optimization; makes it easier to detect empty bodies. Most useful for <clinit> with all-constant initializer. */ @@ -11613,13 +11556,11 @@ java_complete_lhs (tree node) case TRY_FINALLY_EXPR: COMPLETE_CHECK_OP_0 (node); COMPLETE_CHECK_OP_1 (node); - /* Reduce try/finally nodes with an empty try block. */ - if (TREE_OPERAND (node, 0) == empty_stmt_node - || BLOCK_EMPTY_P (TREE_OPERAND (node, 0))) + if (IS_EMPTY_STMT (TREE_OPERAND (node, 0))) + /* Reduce try/finally nodes with an empty try block. */ return TREE_OPERAND (node, 1); - /* Likewise for an empty finally block. */ - if (TREE_OPERAND (node, 1) == empty_stmt_node - || BLOCK_EMPTY_P (TREE_OPERAND (node, 1))) + if (IS_EMPTY_STMT (TREE_OPERAND (node, 1))) + /* Likewise for an empty finally block. */ return TREE_OPERAND (node, 0); CAN_COMPLETE_NORMALLY (node) = (CAN_COMPLETE_NORMALLY (TREE_OPERAND (node, 0)) @@ -11634,7 +11575,7 @@ java_complete_lhs (tree node) TREE_TYPE (node) = void_type_node; POP_LABELED_BLOCK (); - if (LABELED_BLOCK_BODY (node) == empty_stmt_node) + if (IS_EMPTY_STMT (LABELED_BLOCK_BODY (node))) { LABELED_BLOCK_BODY (node) = NULL_TREE; CAN_COMPLETE_NORMALLY (node) = 1; @@ -11791,7 +11732,7 @@ java_complete_lhs (tree node) wfl_op2 = TREE_OPERAND (node, 1); TREE_OPERAND (node, 0) = nn = java_complete_tree (TREE_OPERAND (node, 0)); - if (wfl_op2 == empty_stmt_node) + if (IS_EMPTY_STMT (wfl_op2)) CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (nn); else { @@ -11864,7 +11805,7 @@ java_complete_lhs (tree node) EXPR_WFL_NODE (node) = body; TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (body); CAN_COMPLETE_NORMALLY (node) = CAN_COMPLETE_NORMALLY (body); - if (body == empty_stmt_node || TREE_CONSTANT (body)) + if (IS_EMPTY_STMT (body) || TREE_CONSTANT (body)) { /* Makes it easier to constant fold, detect empty bodies. */ return body; @@ -12000,7 +11941,7 @@ java_complete_lhs (tree node) else DECL_INITIAL (nn) = TREE_OPERAND (node, 1); DECL_FIELD_FINAL_IUD (nn) = 1; - return empty_stmt_node; + return build_java_empty_stmt (); } } if (! flag_emit_class_files) @@ -12444,14 +12385,14 @@ build_wfl_wrap (tree node, int location) return wfl; } -/* Build a super() constructor invocation. Returns empty_stmt_node if +/* Build a super() constructor invocation. Returns an empty statement if we're currently dealing with the class java.lang.Object. */ static tree build_super_invocation (tree mdecl) { if (DECL_CONTEXT (mdecl) == object_type_node) - return empty_stmt_node; + return build_java_empty_stmt (); else { tree super_wfl = build_wfl_node (super_identifier_node); @@ -12786,6 +12727,7 @@ patch_assignment (tree node, tree wfl_op1) ) { TREE_CONSTANT (lvalue) = 1; + TREE_INVARIANT (lvalue) = 1; DECL_INITIAL (lvalue) = new_rhs; } @@ -12798,7 +12740,7 @@ patch_assignment (tree node, tree wfl_op1) case INDIRECT_REF: case COMPONENT_REF: /* Transform a = foo.bar - into a = { int tmp; tmp = foo.bar; tmp; ). + into a = ({int tmp; tmp = foo.bar;}). We need to ensure that if a read from memory fails because of a NullPointerException, a destination variable will remain unchanged. An explicit temporary does what @@ -12817,8 +12759,7 @@ patch_assignment (tree node, tree wfl_op1) DECL_CONTEXT (tmp) = current_function_decl; TREE_TYPE (block) = TREE_TYPE (new_rhs); BLOCK_VARS (block) = tmp; - BLOCK_EXPR_BODY (block) - = build (COMPOUND_EXPR, TREE_TYPE (new_rhs), assignment, tmp); + BLOCK_EXPR_BODY (block) = assignment; TREE_SIDE_EFFECTS (block) = 1; new_rhs = block; } @@ -13340,6 +13281,7 @@ patch_binop (tree node, tree wfl_op1, tree wfl_op2) { parse_warning_context (wfl_operator, "Evaluating this expression will result in an arithmetic exception being thrown"); TREE_CONSTANT (node) = 0; + TREE_INVARIANT (node) = 0; } /* Change the division operator if necessary */ @@ -13926,8 +13868,15 @@ patch_string_cst (tree node) location = alloc_name_constant (CONSTANT_String, node); node = build_ref_from_constant_pool (location); } - TREE_TYPE (node) = string_ptr_type_node; TREE_CONSTANT (node) = 1; + TREE_INVARIANT (node) = 1; + + /* ??? Guessing that the class file code can't handle casts. */ + if (! flag_emit_class_files) + node = convert (string_ptr_type_node, node); + else + TREE_TYPE (node) = string_ptr_type_node; + return node; } @@ -14645,7 +14594,9 @@ patch_new_array_init (tree type, tree node) TREE_TYPE (init) = TREE_TYPE (TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (type)))); TREE_TYPE (node) = promote_type (type); TREE_CONSTANT (init) = all_constant; + TREE_INVARIANT (init) = all_constant; TREE_CONSTANT (node) = all_constant; + TREE_INVARIANT (node) = all_constant; return node; } @@ -14814,7 +14765,7 @@ build_if_else_statement (int location, tree expression, tree if_body, { tree node; if (!else_body) - else_body = empty_stmt_node; + else_body = build_java_empty_stmt (); node = build (COND_EXPR, NULL_TREE, expression, if_body, else_body); EXPR_WFL_LINECOL (node) = location; node = build_debugable_stmt (location, node); @@ -14843,19 +14794,6 @@ patch_if_else_statement (tree node) return error_mark_node; } - if (TREE_CODE (expression) == INTEGER_CST) - { - if (integer_zerop (expression)) - node = TREE_OPERAND (node, 2); - else - node = TREE_OPERAND (node, 1); - if (CAN_COMPLETE_NORMALLY (node) != can_complete_normally) - { - node = build (COMPOUND_EXPR, void_type_node, node, empty_stmt_node); - CAN_COMPLETE_NORMALLY (node) = can_complete_normally; - } - return node; - } TREE_TYPE (node) = void_type_node; TREE_SIDE_EFFECTS (node) = 1; CAN_COMPLETE_NORMALLY (node) = can_complete_normally; @@ -14964,7 +14902,8 @@ build_loop_body (int location, tree condition, int reversed) second = (reversed ? condition : body); return build (COMPOUND_EXPR, NULL_TREE, - build (COMPOUND_EXPR, NULL_TREE, first, second), empty_stmt_node); + build (COMPOUND_EXPR, NULL_TREE, first, second), + build_java_empty_stmt ()); } /* Install CONDITION (if any) and loop BODY (using REVERSED to tell @@ -15004,14 +14943,14 @@ finish_for_loop (int location, tree condition, tree update, tree body) this because the (current interpretation of the) JLS requires that the update expression be considered reachable even if the for loop's body doesn't complete normally. */ - if (update != NULL_TREE && update != empty_stmt_node) + if (update != NULL_TREE && !IS_EMPTY_STMT (update)) { tree up2 = update; if (TREE_CODE (up2) == EXPR_WITH_FILE_LOCATION) up2 = EXPR_WFL_NODE (up2); /* It is possible for the update expression to be an EXPR_WFL_NODE wrapping nothing. */ - if (up2 != NULL_TREE && up2 != empty_stmt_node) + if (up2 != NULL_TREE && !IS_EMPTY_STMT (up2)) { /* Try to detect constraint violations. These would be programming errors somewhere. */ @@ -15323,7 +15262,7 @@ build_assertion (int location, tree condition, tree value) condition = build (TRUTH_ANDIF_EXPR, NULL_TREE, boolean_false_node, condition); if (value == NULL_TREE) - value = empty_stmt_node; + value = build_java_empty_stmt (); return build_if_else_statement (location, condition, value, NULL_TREE); } @@ -15432,8 +15371,8 @@ encapsulate_with_try_catch (int location, tree type_or_name, tree try_stmts, /* Add the catch statements */ add_stmt_to_block (catch_block, NULL_TREE, catch_stmts); - /* Now we can build a CATCH_EXPR */ - catch_block = build1 (CATCH_EXPR, NULL_TREE, catch_block); + /* Now we can build a JAVA_CATCH_EXPR */ + catch_block = build1 (JAVA_CATCH_EXPR, NULL_TREE, catch_block); return build_try_statement (location, try_block, catch_block); } @@ -15474,7 +15413,7 @@ patch_try_statement (tree node) int unreachable; /* At this point, the structure of the catch clause is - CATCH_EXPR (catch node) + JAVA_CATCH_EXPR (catch node) BLOCK (with the decl of the parameter) COMPOUND_EXPR MODIFY_EXPR (assignment of the catch parameter) diff --git a/gcc/java/resource.c b/gcc/java/resource.c index bc2860d..dc42a6f 100644 --- a/gcc/java/resource.c +++ b/gcc/java/resource.c @@ -79,6 +79,7 @@ compile_resource_data (const char *name, const char *buffer, int length) PUSH_FIELD_VALUE (rinit, "data", data); FINISH_RECORD_CONSTRUCTOR (rinit); TREE_CONSTANT (rinit) = 1; + TREE_INVARIANT (rinit) = 1; /* Generate a unique-enough identifier. */ sprintf (buf, "_Jr%d", ++Jr_count); |