From 916b57cedabb2d80ac3e947a682efa3bce15cf4e Mon Sep 17 00:00:00 2001 From: Jeff Sturm Date: Wed, 3 Sep 2003 13:44:43 +0000 Subject: [PATCH] decl.c (java_expand_body): New function. * decl.c (java_expand_body): New function. * expr.c (build_class_init): Set DECL_IGNORED_P. * java-tree.h (start_complete_expand_method, java_expand_body): Declare. * jcf-parse.c (cgraph.h): Include. (java_parse_file): Handle flag_unit_at_a_time. * lang.c (LANG_HOOKS_TREE_INLINING_START_INLINING, LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION): Define. (java_estimate_num_insns): Use walk_tree_without_duplicates. (java_start_inlining): New function. * parse.h (java_finish_classes): Declare. * parse.y: Include cgraph.h. (block): Don't special-case empty block production. (craft_constructor): Set DECL_INLINE. (source_end_java_method): Handle flag_unit_at_a_time. Replace inline code with call to java_expand_body. (start_complete_expand_method): Remove static modifier. (java_expand_method_bodies): Patch function tree for class initialization and/or synchronization as needed. Don't begin RTL expansion yet. (java_expand_classes): Check flag_unit_at_a_time before calling finish_class. (java_finish_classes): New function. (java_complete_lhs): Ensure COMPOUND_EXPR has non-NULL type. (patch_assignment): Set DECL_CONTEXT on temporary variable. (emit_test_initialization): Set DECL_IGNORED_P. From-SVN: r71024 --- gcc/java/ChangeLog | 29 ++++++++++ gcc/java/decl.c | 53 +++++++++++++++++ gcc/java/expr.c | 2 + gcc/java/java-tree.h | 3 + gcc/java/jcf-parse.c | 8 +++ gcc/java/lang.c | 22 ++++++- gcc/java/parse.h | 1 + gcc/java/parse.y | 133 +++++++++++++++++++++++++++++-------------- 8 files changed, 206 insertions(+), 45 deletions(-) diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 4f0db4ae172..3b5253696af 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,32 @@ +2003-09-03 Jeff Sturm + + * decl.c (java_expand_body): New function. + * expr.c (build_class_init): Set DECL_IGNORED_P. + * java-tree.h (start_complete_expand_method, + java_expand_body): Declare. + * jcf-parse.c (cgraph.h): Include. + (java_parse_file): Handle flag_unit_at_a_time. + * lang.c (LANG_HOOKS_TREE_INLINING_START_INLINING, + LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION): Define. + (java_estimate_num_insns): Use walk_tree_without_duplicates. + (java_start_inlining): New function. + * parse.h (java_finish_classes): Declare. + * parse.y: Include cgraph.h. + (block): Don't special-case empty block production. + (craft_constructor): Set DECL_INLINE. + (source_end_java_method): Handle flag_unit_at_a_time. + Replace inline code with call to java_expand_body. + (start_complete_expand_method): Remove static modifier. + (java_expand_method_bodies): Patch function tree for + class initialization and/or synchronization as needed. + Don't begin RTL expansion yet. + (java_expand_classes): Check flag_unit_at_a_time before + calling finish_class. + (java_finish_classes): New function. + (java_complete_lhs): Ensure COMPOUND_EXPR has non-NULL type. + (patch_assignment): Set DECL_CONTEXT on temporary variable. + (emit_test_initialization): Set DECL_IGNORED_P. + 2003-09-03 Roger Sayle * builtins.c (enum builtin_type): Delete unused enumeration. diff --git a/gcc/java/decl.c b/gcc/java/decl.c index c1cebd8046b..90978e48ec8 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -1811,6 +1811,59 @@ end_java_method (void) current_function_decl = NULL_TREE; } +/* Expand a function's body. */ + +void +java_expand_body (tree fndecl) +{ + const char *saved_input_filename = input_filename; + int saved_lineno = input_line; + + current_function_decl = fndecl; + input_filename = DECL_SOURCE_FILE (fndecl); + input_line = DECL_SOURCE_LINE (fndecl); + + timevar_push (TV_EXPAND); + + /* Prepare the function for tree completion. */ + start_complete_expand_method (fndecl); + + if (! flag_emit_class_files && ! flag_emit_xref) + { + /* 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); + } + + /* 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) + { + /* 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); + } + + timevar_pop (TV_EXPAND); + + input_filename = saved_input_filename; + input_line = saved_lineno; + + current_function_decl = NULL_TREE; +} + /* Dump FUNCTION_DECL FN as tree dump PHASE. */ static void diff --git a/gcc/java/expr.c b/gcc/java/expr.c index 7710008fc28..1c7d501f650 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -1710,6 +1710,8 @@ build_class_init (tree clas, tree expr) optimizing class initialization. */ if (!STATIC_CLASS_INIT_OPT_P ()) DECL_BIT_INDEX(*init_test_decl) = -1; + /* Don't emit any symbolic debugging info for this decl. */ + DECL_IGNORED_P (*init_test_decl) = 1; } init = build (CALL_EXPR, void_type_node, diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 0a7a542a9f5..69eb73c3784 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -1297,6 +1297,9 @@ extern void compile_resource_file (const char *, const char *); extern void write_resource_constructor (void); extern void init_resource_processing (void); +extern void start_complete_expand_method (tree); +extern void java_expand_body (tree); + #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL) diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c index 23939271061..f47dbe0897a 100644 --- a/gcc/java/jcf-parse.c +++ b/gcc/java/jcf-parse.c @@ -42,6 +42,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "debug.h" #include "assert.h" #include "tm_p.h" +#include "cgraph.h" #ifdef HAVE_LOCALE_H #include @@ -1119,6 +1120,13 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED) java_expand_classes (); if (!java_report_errors () && !flag_syntax_only) { + if (flag_unit_at_a_time) + { + cgraph_finalize_compilation_unit (); + cgraph_optimize (); + java_finish_classes (); + } + emit_register_classes (); if (flag_indirect_dispatch) emit_offset_symbol_table (); diff --git a/gcc/java/lang.c b/gcc/java/lang.c index 6bddf38335d..5ade4c0844c 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -67,6 +67,7 @@ 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); #ifndef TARGET_OBJECT_SUFFIX # define TARGET_OBJECT_SUFFIX ".o" @@ -253,12 +254,18 @@ struct language_function GTY(()) #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_DECL_OK_FOR_SIBCALL #define LANG_HOOKS_DECL_OK_FOR_SIBCALL java_decl_ok_for_sibcall +#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION +#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION java_expand_body + /* Each front end provides its own. */ const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; @@ -1178,8 +1185,21 @@ static int java_estimate_num_insns (tree decl) { int num = 0; - walk_tree (&DECL_SAVED_TREE (decl), java_estimate_num_insns_1, &num, NULL); + 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; +} + #include "gt-java-lang.h" diff --git a/gcc/java/parse.h b/gcc/java/parse.h index df1fa562844..023410842b2 100644 --- a/gcc/java/parse.h +++ b/gcc/java/parse.h @@ -941,6 +941,7 @@ ATTRIBUTE_NORETURN #endif ; extern void java_expand_classes (void); +extern void java_finish_classes (void); extern GTY(()) struct parser_ctxt *ctxp; extern GTY(()) struct parser_ctxt *ctxp_for_generation; diff --git a/gcc/java/parse.y b/gcc/java/parse.y index a9f8d6ecc6b..8684537268c 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -71,6 +71,7 @@ definitions and other extensions. */ #include "ggc.h" #include "debug.h" #include "tree-inline.h" +#include "cgraph.h" /* Local function prototypes */ static char *java_accstring_lookup (int); @@ -141,7 +142,6 @@ 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 *); @@ -1352,14 +1352,8 @@ variable_initializers: /* 19.11 Production from 14: Blocks and Statements */ block: - OCB_TK CCB_TK - { - /* Store the location of the `}' when doing xrefs */ - if (current_function_decl && flag_emit_xref) - DECL_END_SOURCE_LINE (current_function_decl) = - EXPR_WFL_ADD_COL ($2.location, 1); - $$ = empty_stmt_node; - } + block_begin block_end + { $$ = $2; } | block_begin block_statements block_end { $$ = $3; } ; @@ -5405,6 +5399,7 @@ craft_constructor (tree class_decl, tree args) /* Now, mark the artificial parameters. */ DECL_FUNCTION_NAP (decl) = artificial; DECL_FUNCTION_SYNTHETIC_CTOR (decl) = DECL_CONSTRUCTOR_P (decl) = 1; + DECL_INLINE (decl) = 1; return decl; } @@ -7476,30 +7471,20 @@ source_end_java_method (void) patched. Dump it to a file if the user requested it. */ dump_java_tree (TDI_original, fndecl); - java_optimize_inline (fndecl); - - /* Generate function's code */ - if (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl)) - && ! flag_emit_class_files - && ! flag_emit_xref) - expand_expr_stmt (BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (fndecl))); - - /* pop out of its parameters */ - pushdecl_force_head (DECL_ARGUMENTS (fndecl)); - poplevel (1, 0, 1); - BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; - - /* Generate rtl for function exit. */ - if (! flag_emit_class_files && ! flag_emit_xref) + /* In unit-at-a-time mode, don't expand the method yet. */ + if (DECL_SAVED_TREE (fndecl) && flag_unit_at_a_time) { - input_line = DECL_FUNCTION_LAST_LINE (fndecl); - expand_function_end (); - - /* Run the optimizers and output assembler code for this function. */ - rest_of_compilation (fndecl); + cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl)); + current_function_decl = NULL_TREE; + java_parser_context_restore_global (); + return; } - current_function_decl = NULL_TREE; + java_optimize_inline (fndecl); + + /* Expand the function's body. */ + java_expand_body (fndecl); + java_parser_context_restore_global (); } @@ -7969,7 +7954,7 @@ maybe_yank_clinit (tree mdecl) /* Install the argument from MDECL. Suitable to completion and expansion of mdecl's body. */ -static void +void start_complete_expand_method (tree mdecl) { tree tem; @@ -8112,15 +8097,26 @@ java_expand_method_bodies (tree class) tree decl; for (decl = TYPE_METHODS (class); decl; decl = TREE_CHAIN (decl)) { - if (!DECL_FUNCTION_BODY (decl)) + tree block; + tree body; + + if (! DECL_FUNCTION_BODY (decl)) continue; current_function_decl = decl; - /* Save the function for inlining. */ - if (flag_inline_trees) - DECL_SAVED_TREE (decl) = - BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl)); + block = BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (decl)); + + if (TREE_CODE (block) != BLOCK) + abort (); + + /* Save the function body for 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 @@ -8153,15 +8149,41 @@ java_expand_method_bodies (tree class) } } - /* Prepare the function for RTL expansion */ - start_complete_expand_method (decl); + /* 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; + } - /* Expand function start, generate initialization flag - assignment, and handle synchronized methods. */ - complete_start_java_method (decl); + /* 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); - /* Expand the rest of the function body and terminate - expansion. */ + 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. */ source_end_java_method (); } } @@ -9124,12 +9146,30 @@ java_expand_classes (void) else if (! flag_syntax_only) { java_expand_method_bodies (current_class); - finish_class (); + if (!flag_unit_at_a_time) + finish_class (); } } } } +void +java_finish_classes (void) +{ + static struct parser_ctxt *cur_ctxp = NULL; + for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next) + { + tree current; + ctxp = cur_ctxp; + for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) + { + current_class = TREE_TYPE (current); + outgoing_cpool = TYPE_CPOOL (current_class); + finish_class (); + } + } +} + /* Wrap non WFL PRIMARY around a WFL and set EXPR_WFL_QUALIFICATION to a tree list node containing RIGHT. Fore coming RIGHTs will be chained to this hook. LOCATION contains the location of the @@ -11659,6 +11699,8 @@ java_complete_lhs (tree node) && TREE_CODE (wfl_op2) != DEFAULT_EXPR) unreachable_stmt_error (*ptr); } + if (TREE_TYPE (*ptr) == NULL_TREE) + TREE_TYPE (*ptr) = void_type_node; ptr = next; } *ptr = java_complete_tree (*ptr); @@ -12889,6 +12931,7 @@ patch_assignment (tree node, tree wfl_op1) tree block = build (BLOCK, TREE_TYPE (new_rhs), NULL); tree assignment = build (MODIFY_EXPR, TREE_TYPE (new_rhs), tmp, fold (new_rhs)); + DECL_CONTEXT (tmp) = current_function_decl; BLOCK_VARS (block) = tmp; BLOCK_EXPR_BODY (block) = build (COMPOUND_EXPR, TREE_TYPE (new_rhs), assignment, tmp); @@ -16221,6 +16264,8 @@ emit_test_initialization (void **entry_p, void *info) LOCAL_CLASS_INITIALIZATION_FLAG (decl) = 1; DECL_CONTEXT (decl) = current_function_decl; DECL_INITIAL (decl) = boolean_true_node; + /* Don't emit any symbolic debugging info for this decl. */ + DECL_IGNORED_P (decl) = 1; /* The trick is to find the right context for it. */ block = BLOCK_SUBBLOCKS (GET_CURRENT_BLOCK (current_function_decl));