00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027 #include "system.h"
00028 #include "toplev.h"
00029 #include "tree.h"
00030 #include "tree-inline.h"
00031 #include "rtl.h"
00032 #include "expr.h"
00033 #include "flags.h"
00034 #include "params.h"
00035 #include "input.h"
00036 #include "insn-config.h"
00037 #include "integrate.h"
00038 #include "varray.h"
00039 #include "hashtab.h"
00040 #include "splay-tree.h"
00041 #include "langhooks.h"
00042
00043
00044
00045 #ifndef INLINER_FOR_JAVA
00046 #include "c-common.h"
00047 #else
00048 #include "parse.h"
00049 #include "java-tree.h"
00050 #endif
00051
00052
00053
00054
00055
00056
00057 int flag_inline_trees = 0;
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 typedef struct inline_data
00074 {
00075
00076
00077
00078
00079
00080
00081 varray_type fns;
00082
00083
00084 unsigned first_inlined_fn;
00085
00086
00087
00088 tree ret_label;
00089
00090
00091 splay_tree decl_map;
00092
00093
00094 int in_target_cleanup_p;
00095
00096 varray_type target_exprs;
00097
00098 varray_type inlined_fns;
00099
00100
00101 int inlined_stmts;
00102
00103
00104
00105
00106 bool cloning_p;
00107
00108
00109 htab_t tree_pruner;
00110 } inline_data;
00111
00112
00113
00114 static tree declare_return_variable PARAMS ((inline_data *, tree *));
00115 static tree copy_body_r PARAMS ((tree *, int *, void *));
00116 static tree copy_body PARAMS ((inline_data *));
00117 static tree expand_call_inline PARAMS ((tree *, int *, void *));
00118 static void expand_calls_inline PARAMS ((tree *, inline_data *));
00119 static int inlinable_function_p PARAMS ((tree, inline_data *));
00120 static tree remap_decl PARAMS ((tree, inline_data *));
00121 #ifndef INLINER_FOR_JAVA
00122 static tree initialize_inlined_parameters PARAMS ((inline_data *, tree, tree));
00123 static void remap_block PARAMS ((tree, tree, inline_data *));
00124 static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *));
00125 #else
00126 static tree initialize_inlined_parameters PARAMS ((inline_data *, tree, tree, tree));
00127 static void remap_block PARAMS ((tree *, tree, inline_data *));
00128 static tree add_stmt_to_compound PARAMS ((tree, tree, tree));
00129 #endif
00130 static tree find_alloca_call_1 PARAMS ((tree *, int *, void *));
00131 static tree find_alloca_call PARAMS ((tree));
00132 static tree find_builtin_longjmp_call_1 PARAMS ((tree *, int *, void *));
00133 static tree find_builtin_longjmp_call PARAMS ((tree));
00134
00135
00136
00137
00138 #define INSNS_PER_STMT (10)
00139
00140
00141
00142 static tree
00143 remap_decl (decl, id)
00144 tree decl;
00145 inline_data *id;
00146 {
00147 splay_tree_node n;
00148 tree fn;
00149
00150
00151 fn = VARRAY_TOP_TREE (id->fns);
00152 if (! (*lang_hooks.tree_inlining.auto_var_in_fn_p) (decl, fn))
00153 return NULL_TREE;
00154
00155
00156 n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
00157
00158
00159 if (!n)
00160 {
00161 tree t;
00162
00163
00164 t = copy_decl_for_inlining (decl, fn,
00165 VARRAY_TREE (id->fns, 0));
00166
00167 if (TREE_CODE (t) == LABEL_DECL)
00168 DECL_TOO_LATE (t) = 0;
00169
00170
00171
00172
00173 if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
00174 && TYPE_DOMAIN (TREE_TYPE (t)))
00175 {
00176 TREE_TYPE (t) = copy_node (TREE_TYPE (t));
00177 TYPE_DOMAIN (TREE_TYPE (t))
00178 = copy_node (TYPE_DOMAIN (TREE_TYPE (t)));
00179 walk_tree (&TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (t))),
00180 copy_body_r, id, NULL);
00181 }
00182
00183 #ifndef INLINER_FOR_JAVA
00184 if (! DECL_NAME (t) && TREE_TYPE (t)
00185 && (*lang_hooks.tree_inlining.anon_aggr_type_p) (TREE_TYPE (t)))
00186 {
00187
00188
00189
00190 tree members = NULL;
00191 tree src;
00192
00193 for (src = DECL_ANON_UNION_ELEMS (t); src;
00194 src = TREE_CHAIN (src))
00195 {
00196 tree member = remap_decl (TREE_VALUE (src), id);
00197
00198 if (TREE_PURPOSE (src))
00199 abort ();
00200 members = tree_cons (NULL, member, members);
00201 }
00202 DECL_ANON_UNION_ELEMS (t) = nreverse (members);
00203 }
00204 #endif
00205
00206
00207
00208 n = splay_tree_insert (id->decl_map,
00209 (splay_tree_key) decl,
00210 (splay_tree_value) t);
00211 }
00212
00213 return (tree) n->value;
00214 }
00215
00216 #ifndef INLINER_FOR_JAVA
00217
00218
00219
00220
00221 #else
00222
00223
00224 #endif
00225
00226 static void
00227 #ifndef INLINER_FOR_JAVA
00228 remap_block (scope_stmt, decls, id)
00229 tree scope_stmt;
00230 #else
00231 remap_block (block, decls, id)
00232 tree *block;
00233 #endif
00234 tree decls;
00235 inline_data *id;
00236 {
00237 #ifndef INLINER_FOR_JAVA
00238
00239
00240
00241
00242
00243
00244
00245 if (id->in_target_cleanup_p)
00246 {
00247 SCOPE_STMT_BLOCK (scope_stmt) = NULL_TREE;
00248 return;
00249 }
00250
00251
00252 if (SCOPE_BEGIN_P (scope_stmt) && SCOPE_STMT_BLOCK (scope_stmt))
00253 {
00254 tree old_block;
00255 tree new_block;
00256 tree old_var;
00257 tree fn;
00258
00259
00260 old_block = SCOPE_STMT_BLOCK (scope_stmt);
00261 new_block = make_node (BLOCK);
00262 TREE_USED (new_block) = TREE_USED (old_block);
00263 BLOCK_ABSTRACT_ORIGIN (new_block) = old_block;
00264 SCOPE_STMT_BLOCK (scope_stmt) = new_block;
00265
00266
00267 for (old_var = decls ? decls : BLOCK_VARS (old_block);
00268 old_var;
00269 old_var = TREE_CHAIN (old_var))
00270 {
00271 tree new_var;
00272
00273
00274 new_var = remap_decl (old_var, id);
00275
00276
00277
00278
00279
00280 if (!new_var || !DECL_P (new_var))
00281 ;
00282 else
00283 {
00284 TREE_CHAIN (new_var) = BLOCK_VARS (new_block);
00285 BLOCK_VARS (new_block) = new_var;
00286 }
00287 }
00288
00289 BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block));
00290 fn = VARRAY_TREE (id->fns, 0);
00291 if (id->cloning_p)
00292
00293
00294
00295 (*lang_hooks.decls.insert_block) (new_block);
00296 else
00297 {
00298
00299
00300
00301 tree *first_block;
00302 if (DECL_INITIAL (fn))
00303 first_block = &BLOCK_CHAIN (DECL_INITIAL (fn));
00304 else
00305 first_block = &DECL_INITIAL (fn);
00306 BLOCK_CHAIN (new_block) = *first_block;
00307 *first_block = new_block;
00308 }
00309
00310 splay_tree_insert (id->decl_map,
00311 (splay_tree_key) old_block,
00312 (splay_tree_value) new_block);
00313 }
00314
00315
00316 else if (SCOPE_END_P (scope_stmt) && SCOPE_STMT_BLOCK (scope_stmt))
00317 {
00318 splay_tree_node n;
00319
00320
00321 n = splay_tree_lookup (id->decl_map,
00322 (splay_tree_key) SCOPE_STMT_BLOCK (scope_stmt));
00323 if (! n)
00324 abort ();
00325 SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value;
00326 }
00327 #else
00328 tree old_block;
00329 tree new_block;
00330 tree old_var;
00331 tree fn;
00332
00333
00334 old_block = *block;
00335 new_block = make_node (BLOCK);
00336 TREE_USED (new_block) = TREE_USED (old_block);
00337 BLOCK_ABSTRACT_ORIGIN (new_block) = old_block;
00338 BLOCK_SUBBLOCKS (new_block) = BLOCK_SUBBLOCKS (old_block);
00339 TREE_SIDE_EFFECTS (new_block) = TREE_SIDE_EFFECTS (old_block);
00340 TREE_TYPE (new_block) = TREE_TYPE (old_block);
00341 *block = new_block;
00342
00343
00344 for (old_var = decls ? decls : BLOCK_VARS (old_block);
00345 old_var;
00346 old_var = TREE_CHAIN (old_var))
00347 {
00348 tree new_var;
00349
00350
00351
00352 if (LOCAL_CLASS_INITIALIZATION_FLAG_P (old_var))
00353 {
00354
00355 if (! splay_tree_lookup (id->decl_map, (splay_tree_key) old_var))
00356 {
00357 tree outermost_block;
00358 new_var = remap_decl (old_var, id);
00359 DECL_ABSTRACT_ORIGIN (new_var) = NULL;
00360 outermost_block = DECL_SAVED_TREE (current_function_decl);
00361 TREE_CHAIN (new_var) = BLOCK_VARS (outermost_block);
00362 BLOCK_VARS (outermost_block) = new_var;
00363 }
00364 continue;
00365 }
00366
00367
00368 new_var = remap_decl (old_var, id);
00369
00370
00371
00372
00373
00374 if (!new_var || !DECL_P (new_var))
00375 ;
00376 else
00377 {
00378 TREE_CHAIN (new_var) = BLOCK_VARS (new_block);
00379 BLOCK_VARS (new_block) = new_var;
00380 }
00381 }
00382
00383 BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block));
00384 fn = VARRAY_TREE (id->fns, 0);
00385
00386 splay_tree_insert (id->decl_map,
00387 (splay_tree_key) old_block,
00388 (splay_tree_value) new_block);
00389 #endif
00390 }
00391
00392 #ifndef INLINER_FOR_JAVA
00393
00394
00395 static void
00396 copy_scope_stmt (tp, walk_subtrees, id)
00397 tree *tp;
00398 int *walk_subtrees;
00399 inline_data *id;
00400 {
00401 tree block;
00402
00403
00404
00405
00406
00407 block = SCOPE_STMT_BLOCK (*tp);
00408
00409 copy_tree_r (tp, walk_subtrees, NULL);
00410
00411 SCOPE_STMT_BLOCK (*tp) = block;
00412
00413
00414 remap_block (*tp, NULL_TREE, id);
00415 }
00416 #endif
00417
00418
00419
00420 static tree
00421 copy_body_r (tp, walk_subtrees, data)
00422 tree *tp;
00423 int *walk_subtrees;
00424 void *data;
00425 {
00426 inline_data* id;
00427 tree fn;
00428
00429
00430 id = (inline_data *) data;
00431 fn = VARRAY_TOP_TREE (id->fns);
00432
00433 #if 0
00434
00435
00436 if ((TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == LABEL_DECL)
00437 && DECL_NAMESPACE_SCOPE_P (*tp))
00438 if (! DECL_EXTERNAL (*tp) && ! TREE_STATIC (*tp))
00439 abort ();
00440 #endif
00441
00442 #ifdef INLINER_FOR_JAVA
00443 if (TREE_CODE (*tp) == BLOCK)
00444 remap_block (tp, NULL_TREE, id);
00445 #endif
00446
00447
00448
00449 #ifndef INLINER_FOR_JAVA
00450 if (TREE_CODE (*tp) == RETURN_STMT && id->ret_label)
00451 #else
00452 if (TREE_CODE (*tp) == RETURN_EXPR && id->ret_label)
00453 #endif
00454 {
00455 tree return_stmt = *tp;
00456 tree goto_stmt;
00457
00458
00459 #ifndef INLINER_FOR_JAVA
00460 goto_stmt = build_stmt (GOTO_STMT, id->ret_label);
00461 TREE_CHAIN (goto_stmt) = TREE_CHAIN (return_stmt);
00462 GOTO_FAKE_P (goto_stmt) = 1;
00463 #else
00464 tree assignment = TREE_OPERAND (return_stmt, 0);
00465 goto_stmt = build1 (GOTO_EXPR, void_type_node, id->ret_label);
00466 TREE_SIDE_EFFECTS (goto_stmt) = 1;
00467 #endif
00468
00469
00470
00471
00472 #ifndef INLINER_FOR_JAVA
00473 if (RETURN_STMT_EXPR (return_stmt))
00474 {
00475 *tp = build_stmt (EXPR_STMT,
00476 RETURN_STMT_EXPR (return_stmt));
00477 STMT_IS_FULL_EXPR_P (*tp) = 1;
00478
00479 TREE_CHAIN (*tp) = goto_stmt;
00480 }
00481 #else
00482 if (assignment)
00483 {
00484 copy_body_r (&assignment, walk_subtrees, data);
00485 *tp = build (COMPOUND_EXPR, void_type_node, assignment, goto_stmt);
00486 TREE_SIDE_EFFECTS (*tp) = 1;
00487 }
00488 #endif
00489
00490 else
00491 *tp = goto_stmt;
00492 }
00493
00494
00495
00496
00497 else if ((*lang_hooks.tree_inlining.auto_var_in_fn_p) (*tp, fn))
00498 {
00499 tree new_decl;
00500
00501
00502 new_decl = remap_decl (*tp, id);
00503 if (! new_decl)
00504 abort ();
00505
00506 STRIP_TYPE_NOPS (new_decl);
00507 *tp = new_decl;
00508 }
00509 #if 0
00510 else if (nonstatic_local_decl_p (*tp)
00511 && DECL_CONTEXT (*tp) != VARRAY_TREE (id->fns, 0))
00512 abort ();
00513 #endif
00514 else if (TREE_CODE (*tp) == SAVE_EXPR)
00515 remap_save_expr (tp, id->decl_map, VARRAY_TREE (id->fns, 0),
00516 walk_subtrees);
00517 else if (TREE_CODE (*tp) == UNSAVE_EXPR)
00518
00519 abort ();
00520 #ifndef INLINER_FOR_JAVA
00521
00522
00523 else if (TREE_CODE (*tp) == SCOPE_STMT && !id->in_target_cleanup_p)
00524 copy_scope_stmt (tp, walk_subtrees, id);
00525 #else
00526 else if (TREE_CODE (*tp) == LABELED_BLOCK_EXPR)
00527 {
00528
00529
00530
00531 tree new_block = copy_node (*tp);
00532 splay_tree_insert (id->decl_map,
00533 (splay_tree_key) *tp,
00534 (splay_tree_value) new_block);
00535 *tp = new_block;
00536 }
00537 else if (TREE_CODE (*tp) == EXIT_BLOCK_EXPR)
00538 {
00539 splay_tree_node n
00540 = splay_tree_lookup (id->decl_map,
00541 (splay_tree_key) TREE_OPERAND (*tp, 0));
00542
00543 if (! n)
00544 abort ();
00545 *tp = copy_node (*tp);
00546 TREE_OPERAND (*tp, 0) = (tree) n->value;
00547 }
00548 #endif
00549
00550
00551 else
00552 {
00553 copy_tree_r (tp, walk_subtrees, NULL);
00554
00555
00556
00557 if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3))
00558 {
00559 TREE_OPERAND (*tp, 1) = TREE_OPERAND (*tp, 3);
00560 TREE_OPERAND (*tp, 3) = NULL_TREE;
00561 }
00562 else if (TREE_CODE (*tp) == MODIFY_EXPR
00563 && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1)
00564 && ((*lang_hooks.tree_inlining.auto_var_in_fn_p)
00565 (TREE_OPERAND (*tp, 0), fn)))
00566 {
00567
00568
00569
00570 tree decl = TREE_OPERAND (*tp, 0), value;
00571 splay_tree_node n;
00572
00573 n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
00574 if (n)
00575 {
00576 value = (tree) n->value;
00577 STRIP_TYPE_NOPS (value);
00578 if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value))
00579 *tp = value;
00580 }
00581 }
00582 }
00583
00584
00585 return NULL_TREE;
00586 }
00587
00588
00589
00590
00591 static tree
00592 copy_body (id)
00593 inline_data *id;
00594 {
00595 tree body;
00596
00597 body = DECL_SAVED_TREE (VARRAY_TOP_TREE (id->fns));
00598 walk_tree (&body, copy_body_r, id, NULL);
00599
00600 return body;
00601 }
00602
00603
00604
00605
00606 static tree
00607 #ifndef INLINER_FOR_JAVA
00608 initialize_inlined_parameters (id, args, fn)
00609 #else
00610 initialize_inlined_parameters (id, args, fn, block)
00611 #endif
00612 inline_data *id;
00613 tree args;
00614 tree fn;
00615 #ifdef INLINER_FOR_JAVA
00616 tree block;
00617 #endif
00618 {
00619 tree init_stmts;
00620 tree parms;
00621 tree a;
00622 tree p;
00623 #ifdef INLINER_FOR_JAVA
00624 tree vars = NULL_TREE;
00625 #endif
00626
00627
00628 parms = DECL_ARGUMENTS (fn);
00629
00630
00631 init_stmts = NULL_TREE;
00632
00633
00634
00635 for (p = parms, a = args; p;
00636 a = a ? TREE_CHAIN (a) : a, p = TREE_CHAIN (p))
00637 {
00638 #ifndef INLINER_FOR_JAVA
00639 tree init_stmt;
00640 tree cleanup;
00641 #endif
00642 tree var;
00643 tree value;
00644 tree var_sub;
00645
00646
00647 value = (*lang_hooks.tree_inlining.convert_parm_for_inlining)
00648 (p, a ? TREE_VALUE (a) : NULL_TREE, fn);
00649
00650
00651
00652
00653 if (TREE_READONLY (p)
00654 && !TREE_ADDRESSABLE (p)
00655 && value && !TREE_SIDE_EFFECTS (value))
00656 {
00657
00658 value = fold (DECL_P (value) ? decl_constant_value (value) : value);
00659
00660
00661
00662
00663
00664
00665 if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value))
00666 {
00667
00668
00669
00670 if (DECL_P (value))
00671 value = build1 (NOP_EXPR, TREE_TYPE (value), value);
00672
00673
00674 else if (TREE_TYPE (value) != TREE_TYPE (p))
00675 value = fold (build1 (NOP_EXPR, TREE_TYPE (p), value));
00676
00677 splay_tree_insert (id->decl_map,
00678 (splay_tree_key) p,
00679 (splay_tree_value) value);
00680 continue;
00681 }
00682 }
00683
00684
00685 var = copy_decl_for_inlining (p, fn, VARRAY_TREE (id->fns, 0));
00686
00687
00688
00689
00690 if (TREE_TYPE (var) != TREE_TYPE (p)
00691 && POINTER_TYPE_P (TREE_TYPE (var))
00692 && TREE_TYPE (TREE_TYPE (var)) == TREE_TYPE (p))
00693 var_sub = build1 (INDIRECT_REF, TREE_TYPE (p), var);
00694 else
00695 var_sub = var;
00696
00697
00698
00699
00700 splay_tree_insert (id->decl_map,
00701 (splay_tree_key) p,
00702 (splay_tree_value) var_sub);
00703
00704
00705 #ifndef INLINER_FOR_JAVA
00706 init_stmt = build_stmt (DECL_STMT, var);
00707 TREE_CHAIN (init_stmt) = init_stmts;
00708 init_stmts = init_stmt;
00709 #else
00710 TREE_CHAIN (var) = vars;
00711 vars = var;
00712 #endif
00713
00714
00715
00716
00717
00718
00719 if (! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (p)))
00720 #ifndef INLINER_FOR_JAVA
00721 DECL_INITIAL (var) = value;
00722 else
00723 {
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 TREE_READONLY (var) = 0;
00734
00735
00736 init_stmt = build_stmt (EXPR_STMT,
00737 build (INIT_EXPR, TREE_TYPE (p),
00738 var, value));
00739
00740
00741
00742 TREE_CHAIN (init_stmt) = init_stmts;
00743 init_stmts = init_stmt;
00744 }
00745
00746
00747 cleanup = (*lang_hooks.maybe_build_cleanup) (var);
00748 if (cleanup)
00749 {
00750 tree cleanup_stmt;
00751
00752 cleanup_stmt = build_stmt (CLEANUP_STMT, var, cleanup);
00753
00754
00755 TREE_CHAIN (cleanup_stmt) = init_stmts;
00756 init_stmts = cleanup_stmt;
00757 }
00758 #else
00759 {
00760 tree assignment = build (MODIFY_EXPR, TREE_TYPE (p), var, value);
00761 init_stmts = add_stmt_to_compound (init_stmts, TREE_TYPE (p),
00762 assignment);
00763 }
00764 else
00765 {
00766
00767
00768
00769 abort ();
00770 }
00771 #endif
00772 }
00773
00774 #ifndef INLINER_FOR_JAVA
00775
00776 for (; a; a = TREE_CHAIN (a))
00777 {
00778 tree init_stmt;
00779 tree value = TREE_VALUE (a);
00780
00781 if (! value || ! TREE_SIDE_EFFECTS (value))
00782 continue;
00783
00784 init_stmt = build_stmt (EXPR_STMT, value);
00785 TREE_CHAIN (init_stmt) = init_stmts;
00786 init_stmts = init_stmt;
00787 }
00788
00789
00790
00791 return nreverse (init_stmts);
00792 #else
00793 BLOCK_VARS (block) = nreverse (vars);
00794 return init_stmts;
00795 #endif
00796 }
00797
00798
00799
00800
00801
00802
00803 #ifndef INLINER_FOR_JAVA
00804 static tree
00805 declare_return_variable (id, use_stmt)
00806 struct inline_data *id;
00807 tree *use_stmt;
00808 #else
00809 static tree
00810 declare_return_variable (id, var)
00811 struct inline_data *id;
00812 tree *var;
00813 #endif
00814 {
00815 tree fn = VARRAY_TOP_TREE (id->fns);
00816 tree result = DECL_RESULT (fn);
00817 #ifndef INLINER_FOR_JAVA
00818 tree var;
00819 #endif
00820 int need_return_decl = 1;
00821
00822
00823
00824 if (!result || VOID_TYPE_P (TREE_TYPE (result)))
00825 {
00826 #ifndef INLINER_FOR_JAVA
00827 *use_stmt = NULL_TREE;
00828 #else
00829 *var = NULL_TREE;
00830 #endif
00831 return NULL_TREE;
00832 }
00833
00834 #ifndef INLINER_FOR_JAVA
00835 var = ((*lang_hooks.tree_inlining.copy_res_decl_for_inlining)
00836 (result, fn, VARRAY_TREE (id->fns, 0), id->decl_map,
00837 &need_return_decl, &id->target_exprs));
00838
00839
00840
00841
00842 splay_tree_insert (id->decl_map,
00843 (splay_tree_key) result,
00844 (splay_tree_value) var);
00845
00846
00847
00848 if (TREE_TYPE (var) == TREE_TYPE (TREE_TYPE (fn)))
00849 *use_stmt = build_stmt (EXPR_STMT, var);
00850 else
00851 *use_stmt = build_stmt (EXPR_STMT,
00852 build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)),
00853 var));
00854 TREE_ADDRESSABLE (*use_stmt) = 1;
00855
00856
00857
00858 if (need_return_decl)
00859 return build_stmt (DECL_STMT, var);
00860 #else
00861 *var = ((*lang_hooks.tree_inlining.copy_res_decl_for_inlining)
00862 (result, fn, VARRAY_TREE (id->fns, 0), id->decl_map,
00863 &need_return_decl, NULL_TREE));
00864
00865 splay_tree_insert (id->decl_map,
00866 (splay_tree_key) result,
00867 (splay_tree_value) *var);
00868 DECL_IGNORED_P (*var) = 1;
00869 if (need_return_decl)
00870 return *var;
00871 #endif
00872
00873
00874 else
00875 return NULL_TREE;
00876 }
00877
00878
00879
00880 int
00881 tree_inlinable_function_p (fn)
00882 tree fn;
00883 {
00884 return inlinable_function_p (fn, NULL);
00885 }
00886
00887
00888 static tree
00889 find_alloca_call_1 (tp, walk_subtrees, data)
00890 tree *tp;
00891 int *walk_subtrees ATTRIBUTE_UNUSED;
00892 void *data ATTRIBUTE_UNUSED;
00893 {
00894 if (alloca_call_p (*tp))
00895 return *tp;
00896 return NULL;
00897 }
00898
00899
00900 static tree
00901 find_alloca_call (exp)
00902 tree exp;
00903 {
00904 return walk_tree_without_duplicates (&exp, find_alloca_call_1, NULL);
00905 }
00906
00907 static tree
00908 find_builtin_longjmp_call_1 (tp, walk_subtrees, data)
00909 tree *tp;
00910 int *walk_subtrees ATTRIBUTE_UNUSED;
00911 void *data ATTRIBUTE_UNUSED;
00912 {
00913 tree exp = *tp, decl;
00914
00915 if (TREE_CODE (exp) == CALL_EXPR
00916 && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
00917 && (decl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
00918 TREE_CODE (decl) == FUNCTION_DECL)
00919 && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
00920 && DECL_FUNCTION_CODE (decl) == BUILT_IN_LONGJMP)
00921 return decl;
00922
00923 return NULL;
00924 }
00925
00926 static tree
00927 find_builtin_longjmp_call (exp)
00928 tree exp;
00929 {
00930 return walk_tree_without_duplicates (&exp, find_builtin_longjmp_call_1, NULL);
00931 }
00932
00933
00934
00935
00936
00937 static int
00938 inlinable_function_p (fn, id)
00939 tree fn;
00940 inline_data *id;
00941 {
00942 int inlinable;
00943 int currfn_insns;
00944 int max_inline_insns_single = MAX_INLINE_INSNS_SINGLE;
00945
00946
00947
00948 if (DECL_UNINLINABLE (fn))
00949 return 0;
00950
00951
00952 inlinable = 0;
00953
00954
00955
00956
00957 if (DID_INLINE_FUNC (fn))
00958 max_inline_insns_single = MAX_INLINE_INSNS_AUTO;
00959
00960
00961 currfn_insns = DECL_NUM_STMTS (fn) * INSNS_PER_STMT;
00962
00963
00964 if (! flag_inline_trees)
00965 ;
00966
00967
00968
00969
00970
00971
00972 else if (! DECL_INLINE (fn))
00973 ;
00974 #ifdef INLINER_FOR_JAVA
00975
00976 else if (METHOD_SYNCHRONIZED (fn))
00977 ;
00978 #endif
00979
00980
00981
00982 else if (! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn)
00983 && currfn_insns > max_inline_insns_single)
00984 ;
00985
00986
00987
00988
00989
00990
00991 else if (find_builtin_longjmp_call (DECL_SAVED_TREE (fn)))
00992 ;
00993
00994
00995
00996
00997 else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL
00998 && find_alloca_call (DECL_SAVED_TREE (fn)))
00999 ;
01000
01001
01002
01003
01004 else
01005 inlinable = 1;
01006
01007
01008 DECL_UNINLINABLE (fn) = ! inlinable;
01009
01010
01011
01012 if (! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn)
01013 && inlinable
01014 && currfn_insns > MIN_INLINE_INSNS)
01015 {
01016 int sum_insns = (id ? id->inlined_stmts : 0) * INSNS_PER_STMT
01017 + currfn_insns;
01018
01019
01020
01021 if (sum_insns > MAX_INLINE_INSNS * 128)
01022 inlinable = 0;
01023
01024
01025
01026
01027 else if (sum_insns > MAX_INLINE_INSNS)
01028 {
01029 int max_curr = MAX_INLINE_INSNS_SINGLE
01030 - (sum_insns - MAX_INLINE_INSNS) / MAX_INLINE_SLOPE;
01031 if (currfn_insns > max_curr)
01032 inlinable = 0;
01033 }
01034 }
01035
01036 if (inlinable && (*lang_hooks.tree_inlining.cannot_inline_tree_fn) (&fn))
01037 inlinable = 0;
01038
01039
01040
01041 if (! DECL_SAVED_TREE (fn))
01042 inlinable = 0;
01043
01044
01045 if (! inlinable || DECL_UNINLINABLE (fn))
01046 return 0;
01047
01048
01049
01050 if (id)
01051 {
01052 size_t i;
01053
01054 for (i = 0; i < VARRAY_ACTIVE_SIZE (id->fns); ++i)
01055 if (VARRAY_TREE (id->fns, i) == fn)
01056 return 0;
01057
01058 if (DECL_INLINED_FNS (fn))
01059 {
01060 int j;
01061 tree inlined_fns = DECL_INLINED_FNS (fn);
01062
01063 for (j = 0; j < TREE_VEC_LENGTH (inlined_fns); ++j)
01064 if (TREE_VEC_ELT (inlined_fns, j) == VARRAY_TREE (id->fns, 0))
01065 return 0;
01066 }
01067 }
01068
01069
01070 return inlinable;
01071 }
01072
01073
01074
01075 static tree
01076 expand_call_inline (tp, walk_subtrees, data)
01077 tree *tp;
01078 int *walk_subtrees;
01079 void *data;
01080 {
01081 inline_data *id;
01082 tree t;
01083 tree expr;
01084 tree stmt;
01085 #ifndef INLINER_FOR_JAVA
01086 tree chain;
01087 tree scope_stmt;
01088 tree use_stmt;
01089 #else
01090 tree retvar;
01091 #endif
01092 tree fn;
01093 tree arg_inits;
01094 tree *inlined_body;
01095 splay_tree st;
01096
01097
01098 id = (inline_data *) data;
01099 t = *tp;
01100
01101
01102
01103 if (TREE_CODE (*tp) == TARGET_EXPR)
01104 {
01105 #ifndef INLINER_FOR_JAVA
01106 int i, len = first_rtl_op (TARGET_EXPR);
01107
01108
01109 *walk_subtrees = 0;
01110
01111
01112 VARRAY_PUSH_TREE (id->target_exprs, *tp);
01113
01114
01115
01116
01117 for (i = 0; i < len; ++i)
01118 {
01119 if (i == 2)
01120 ++id->in_target_cleanup_p;
01121 walk_tree (&TREE_OPERAND (*tp, i), expand_call_inline, data,
01122 id->tree_pruner);
01123 if (i == 2)
01124 --id->in_target_cleanup_p;
01125 }
01126
01127
01128 VARRAY_POP (id->target_exprs);
01129
01130 return NULL_TREE;
01131 #else
01132 abort ();
01133 #endif
01134 }
01135 else if (TREE_CODE (t) == EXPR_WITH_FILE_LOCATION)
01136 {
01137
01138 *walk_subtrees = 0;
01139
01140 push_srcloc (EXPR_WFL_FILENAME (t), EXPR_WFL_LINENO (t));
01141 walk_tree (&EXPR_WFL_NODE (t), expand_call_inline, data,
01142 id->tree_pruner);
01143
01144 pop_srcloc ();
01145
01146 return NULL_TREE;
01147 }
01148
01149 if (TYPE_P (t))
01150
01151
01152
01153 *walk_subtrees = 0;
01154
01155
01156 if (TREE_CODE (t) != CALL_EXPR)
01157 return NULL_TREE;
01158
01159
01160
01161 fn = get_callee_fndecl (t);
01162 if (!fn)
01163 return NULL_TREE;
01164
01165
01166
01167
01168
01169
01170
01171
01172 if (! DECL_INITIAL (fn)
01173 && DECL_ABSTRACT_ORIGIN (fn)
01174 && DECL_SAVED_TREE (DECL_ABSTRACT_ORIGIN (fn)))
01175 fn = DECL_ABSTRACT_ORIGIN (fn);
01176
01177
01178
01179 if (!inlinable_function_p (fn, id))
01180 {
01181 if (warn_inline && DECL_INLINE (fn) && !DID_INLINE_FUNC (fn)
01182 && !DECL_IN_SYSTEM_HEADER (fn))
01183 {
01184 warning_with_decl (fn, "inlining failed in call to `%s'");
01185 warning ("called from here");
01186 }
01187 return NULL_TREE;
01188 }
01189
01190 if (! (*lang_hooks.tree_inlining.start_inlining) (fn))
01191 return NULL_TREE;
01192
01193
01194
01195
01196
01197
01198 push_srcloc (DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn));
01199
01200 #ifndef INLINER_FOR_JAVA
01201
01202
01203
01204
01205
01206 expr = build1 (STMT_EXPR, TREE_TYPE (TREE_TYPE (fn)), make_node (COMPOUND_STMT));
01207
01208 STMT_EXPR_NO_SCOPE (expr) = 1;
01209 stmt = STMT_EXPR_STMT (expr);
01210 #else
01211
01212
01213
01214
01215 stmt = NULL;
01216 expr = build (BLOCK, TREE_TYPE (TREE_TYPE (fn)), stmt);
01217 #endif
01218
01219
01220
01221 st = id->decl_map;
01222 id->decl_map = splay_tree_new (splay_tree_compare_pointers,
01223 NULL, NULL);
01224
01225
01226 #ifndef INLINER_FOR_JAVA
01227 arg_inits = initialize_inlined_parameters (id, TREE_OPERAND (t, 1), fn);
01228
01229
01230
01231
01232 expand_calls_inline (&arg_inits, id);
01233
01234 COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), arg_inits);
01235 #else
01236 arg_inits = initialize_inlined_parameters (id, TREE_OPERAND (t, 1), fn, expr);
01237 if (arg_inits)
01238 {
01239
01240
01241
01242
01243 expand_calls_inline (&arg_inits, id);
01244
01245
01246 BLOCK_EXPR_BODY (expr) = add_stmt_to_compound (BLOCK_EXPR_BODY (expr),
01247 TREE_TYPE (arg_inits),
01248 arg_inits);
01249 }
01250 #endif
01251
01252
01253
01254 VARRAY_PUSH_TREE (id->fns, fn);
01255
01256
01257
01258 if (! DECL_INLINED_FNS (fn))
01259 {
01260 int i;
01261
01262 for (i = VARRAY_ACTIVE_SIZE (id->inlined_fns) - 1; i >= 0; i--)
01263 if (VARRAY_TREE (id->inlined_fns, i) == fn)
01264 break;
01265 if (i < 0)
01266 VARRAY_PUSH_TREE (id->inlined_fns, fn);
01267 }
01268
01269
01270
01271 id->ret_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
01272 DECL_CONTEXT (id->ret_label) = VARRAY_TREE (id->fns, 0);
01273
01274 if (! DECL_INITIAL (fn)
01275 || TREE_CODE (DECL_INITIAL (fn)) != BLOCK)
01276 abort ();
01277
01278 #ifndef INLINER_FOR_JAVA
01279
01280
01281
01282 scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn));
01283 SCOPE_BEGIN_P (scope_stmt) = 1;
01284 SCOPE_NO_CLEANUPS_P (scope_stmt) = 1;
01285 remap_block (scope_stmt, DECL_ARGUMENTS (fn), id);
01286 TREE_CHAIN (scope_stmt) = COMPOUND_BODY (stmt);
01287 COMPOUND_BODY (stmt) = scope_stmt;
01288
01289
01290
01291 if (SCOPE_STMT_BLOCK (scope_stmt))
01292 BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope_stmt)) = DECL_ORIGIN (fn);
01293
01294
01295 COMPOUND_BODY (stmt)
01296 = chainon (COMPOUND_BODY (stmt),
01297 declare_return_variable (id, &use_stmt));
01298 #else
01299 {
01300
01301 tree decl = declare_return_variable (id, &retvar);
01302 if (retvar)
01303 {
01304 tree *next = &BLOCK_VARS (expr);
01305 while (*next)
01306 next = &TREE_CHAIN (*next);
01307 *next = decl;
01308 }
01309 }
01310 #endif
01311
01312
01313
01314 #ifndef INLINER_FOR_JAVA
01315 inlined_body = &COMPOUND_BODY (stmt);
01316 while (*inlined_body)
01317 inlined_body = &TREE_CHAIN (*inlined_body);
01318 *inlined_body = copy_body (id);
01319 #else
01320 {
01321 tree new_body;
01322 java_inlining_map_static_initializers (fn, id->decl_map);
01323 new_body = copy_body (id);
01324 TREE_TYPE (new_body) = TREE_TYPE (TREE_TYPE (fn));
01325 BLOCK_EXPR_BODY (expr)
01326 = add_stmt_to_compound (BLOCK_EXPR_BODY (expr),
01327 TREE_TYPE (new_body), new_body);
01328 inlined_body = &BLOCK_EXPR_BODY (expr);
01329 }
01330 #endif
01331
01332
01333
01334
01335 #ifndef INLINER_FOR_JAVA
01336 COMPOUND_BODY (stmt)
01337 = chainon (COMPOUND_BODY (stmt),
01338 build_stmt (LABEL_STMT, id->ret_label));
01339 #else
01340 {
01341 tree label = build1 (LABEL_EXPR, void_type_node, id->ret_label);
01342 BLOCK_EXPR_BODY (expr)
01343 = add_stmt_to_compound (BLOCK_EXPR_BODY (expr), void_type_node, label);
01344 TREE_SIDE_EFFECTS (label) = TREE_SIDE_EFFECTS (t);
01345 }
01346 #endif
01347
01348
01349
01350 #ifndef INLINER_FOR_JAVA
01351 COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), use_stmt);
01352
01353
01354 scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn));
01355 SCOPE_NO_CLEANUPS_P (scope_stmt) = 1;
01356 remap_block (scope_stmt, NULL_TREE, id);
01357 COMPOUND_BODY (stmt)
01358 = chainon (COMPOUND_BODY (stmt), scope_stmt);
01359 #else
01360 if (retvar)
01361 {
01362
01363
01364 if (TREE_TYPE (TREE_TYPE (fn)) != TREE_TYPE (retvar))
01365 retvar = build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)), retvar);
01366 BLOCK_EXPR_BODY (expr)
01367 = add_stmt_to_compound (BLOCK_EXPR_BODY (expr),
01368 TREE_TYPE (retvar), retvar);
01369 }
01370
01371 java_inlining_merge_static_initializers (fn, id->decl_map);
01372 #endif
01373
01374
01375 splay_tree_delete (id->decl_map);
01376 id->decl_map = st;
01377
01378
01379 TREE_SIDE_EFFECTS (expr) = TREE_SIDE_EFFECTS (t);
01380
01381
01382
01383
01384 #ifndef INLINER_FOR_JAVA
01385 chain = TREE_CHAIN (*tp);
01386 *tp = build_expr_wfl (expr, DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn),
01387 0);
01388 #else
01389 *tp = build_expr_wfl (expr, DECL_SOURCE_FILE (fn),
01390 DECL_SOURCE_LINE_FIRST(fn),
01391 0);
01392 #endif
01393 EXPR_WFL_EMIT_LINE_NOTE (*tp) = 1;
01394 #ifndef INLINER_FOR_JAVA
01395 TREE_CHAIN (*tp) = chain;
01396 #endif
01397 pop_srcloc ();
01398
01399
01400
01401
01402 TREE_USED (*tp) = 1;
01403
01404
01405 DECL_NUM_STMTS (VARRAY_TREE (id->fns, 0)) += DECL_NUM_STMTS (fn);
01406
01407 id->inlined_stmts += DECL_NUM_STMTS (fn) - 1;
01408
01409
01410 expand_calls_inline (inlined_body, id);
01411 VARRAY_POP (id->fns);
01412
01413
01414
01415 if (VARRAY_ACTIVE_SIZE (id->fns) == id->first_inlined_fn)
01416 id->inlined_stmts = 0;
01417
01418
01419 *walk_subtrees = 0;
01420
01421 (*lang_hooks.tree_inlining.end_inlining) (fn);
01422
01423
01424 return NULL_TREE;
01425 }
01426
01427
01428
01429 static void
01430 expand_calls_inline (tp, id)
01431 tree *tp;
01432 inline_data *id;
01433 {
01434
01435
01436
01437
01438
01439
01440 walk_tree (tp, expand_call_inline, id, id->tree_pruner);
01441 }
01442
01443
01444
01445 void
01446 optimize_inline_calls (fn)
01447 tree fn;
01448 {
01449 inline_data id;
01450 tree prev_fn;
01451
01452
01453 memset (&id, 0, sizeof (id));
01454
01455
01456 VARRAY_TREE_INIT (id.fns, 32, "fns");
01457 VARRAY_PUSH_TREE (id.fns, fn);
01458
01459 prev_fn = NULL_TREE;
01460 if (current_function_decl)
01461 {
01462 VARRAY_PUSH_TREE (id.fns, current_function_decl);
01463 prev_fn = current_function_decl;
01464 }
01465
01466 prev_fn = ((*lang_hooks.tree_inlining.add_pending_fn_decls)
01467 (&id.fns, prev_fn));
01468
01469
01470 VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs");
01471
01472
01473 VARRAY_TREE_INIT (id.inlined_fns, 32, "inlined_fns");
01474
01475
01476
01477 id.first_inlined_fn = VARRAY_ACTIVE_SIZE (id.fns);
01478
01479
01480
01481 id.tree_pruner = htab_create (37, htab_hash_pointer,
01482 htab_eq_pointer, NULL);
01483 expand_calls_inline (&DECL_SAVED_TREE (fn), &id);
01484
01485
01486 htab_delete (id.tree_pruner);
01487 if (DECL_LANG_SPECIFIC (fn))
01488 {
01489 tree ifn = make_tree_vec (VARRAY_ACTIVE_SIZE (id.inlined_fns));
01490
01491 if (VARRAY_ACTIVE_SIZE (id.inlined_fns))
01492 memcpy (&TREE_VEC_ELT (ifn, 0), &VARRAY_TREE (id.inlined_fns, 0),
01493 VARRAY_ACTIVE_SIZE (id.inlined_fns) * sizeof (tree));
01494 DECL_INLINED_FNS (fn) = ifn;
01495 }
01496 }
01497
01498
01499
01500
01501
01502 void
01503 clone_body (clone, fn, arg_map)
01504 tree clone, fn;
01505 void *arg_map;
01506 {
01507 inline_data id;
01508
01509
01510
01511
01512
01513 memset (&id, 0, sizeof (id));
01514 VARRAY_TREE_INIT (id.fns, 2, "fns");
01515 VARRAY_PUSH_TREE (id.fns, clone);
01516 VARRAY_PUSH_TREE (id.fns, fn);
01517 id.decl_map = (splay_tree)arg_map;
01518
01519
01520
01521 id.cloning_p = true;
01522
01523
01524 TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id);
01525 }
01526
01527
01528
01529
01530
01531
01532
01533
01534 tree
01535 walk_tree (tp, func, data, htab_)
01536 tree *tp;
01537 walk_tree_fn func;
01538 void *data;
01539 void *htab_;
01540 {
01541 htab_t htab = (htab_t) htab_;
01542 enum tree_code code;
01543 int walk_subtrees;
01544 tree result;
01545
01546 #define WALK_SUBTREE(NODE) \
01547 do \
01548 { \
01549 result = walk_tree (&(NODE), func, data, htab); \
01550 if (result) \
01551 return result; \
01552 } \
01553 while (0)
01554
01555 #define WALK_SUBTREE_TAIL(NODE) \
01556 do \
01557 { \
01558 tp = & (NODE); \
01559 goto tail_recurse; \
01560 } \
01561 while (0)
01562
01563 tail_recurse:
01564
01565 if (!*tp)
01566 return NULL_TREE;
01567
01568 if (htab)
01569 {
01570 void **slot;
01571
01572
01573
01574 slot = htab_find_slot (htab, *tp, INSERT);
01575 if (*slot)
01576 return NULL_TREE;
01577 *slot = *tp;
01578 }
01579
01580
01581 walk_subtrees = 1;
01582 result = (*func) (tp, &walk_subtrees, data);
01583
01584
01585 if (result)
01586 return result;
01587
01588 code = TREE_CODE (*tp);
01589
01590 #ifndef INLINER_FOR_JAVA
01591
01592
01593 if (!walk_subtrees)
01594 {
01595 if (statement_code_p (code) || code == TREE_LIST
01596 || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp))
01597
01598 WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
01599 else
01600 return NULL_TREE;
01601 }
01602
01603
01604 if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
01605 || TREE_CODE_CLASS (code) == 'r'
01606 || TREE_CODE_CLASS (code) == 's')
01607 #else
01608 if (code != EXIT_BLOCK_EXPR
01609 && code != SAVE_EXPR
01610 && (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
01611 || TREE_CODE_CLASS (code) == 'r'
01612 || TREE_CODE_CLASS (code) == 's'))
01613 #endif
01614 {
01615 int i, len;
01616
01617 #ifndef INLINER_FOR_JAVA
01618
01619
01620 if (statement_code_p (code) && !STMT_LINENO_FOR_FN_P (*tp))
01621 lineno = STMT_LINENO (*tp);
01622 #endif
01623
01624
01625 len = first_rtl_op (code);
01626
01627
01628 if (code == TARGET_EXPR
01629 && TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1))
01630 --len;
01631
01632
01633 for (i = 0; i < len; ++i)
01634 WALK_SUBTREE (TREE_OPERAND (*tp, i));
01635
01636 #ifdef SGI_MONGOOSE
01637
01638
01639 if (TREE_TYPE (*tp) && TREE_TYPE (*tp) != ERROR_MARK
01640 && code == NOP_EXPR)
01641 WALK_SUBTREE (TREE_TYPE (*tp));
01642 #endif
01643 #ifndef INLINER_FOR_JAVA
01644
01645
01646 if (statement_code_p (code))
01647 {
01648 if (code == DECL_STMT
01649 && DECL_STMT_DECL (*tp)
01650 && DECL_P (DECL_STMT_DECL (*tp)))
01651 {
01652
01653
01654
01655
01656
01657 WALK_SUBTREE (DECL_INITIAL (DECL_STMT_DECL (*tp)));
01658 WALK_SUBTREE (DECL_SIZE (DECL_STMT_DECL (*tp)));
01659 WALK_SUBTREE (DECL_SIZE_UNIT (DECL_STMT_DECL (*tp)));
01660 }
01661
01662
01663 WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
01664 }
01665
01666 #endif
01667
01668 return NULL_TREE;
01669 }
01670 else if (TREE_CODE_CLASS (code) == 'd')
01671 {
01672 WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
01673 }
01674 else if (TREE_CODE_CLASS (code) == 't')
01675 {
01676 WALK_SUBTREE (TYPE_SIZE (*tp));
01677 WALK_SUBTREE (TYPE_SIZE_UNIT (*tp));
01678 #ifdef SGI_MONGOOSE
01679 if ((code == POINTER_TYPE || code == REFERENCE_TYPE
01680 || code == ARRAY_TYPE)
01681 && variably_modified_type_p (TREE_TYPE (*tp)))
01682 WALK_SUBTREE (TREE_TYPE (*tp));
01683 if (code == ARRAY_TYPE
01684 && TYPE_DOMAIN (*tp))
01685 WALK_SUBTREE (TYPE_MAX_VALUE (TYPE_DOMAIN (*tp)));
01686
01687 #endif
01688
01689 }
01690
01691 result = (*lang_hooks.tree_inlining.walk_subtrees) (tp, &walk_subtrees, func,
01692 data, htab);
01693 if (result || ! walk_subtrees)
01694 return result;
01695
01696
01697
01698 switch (code)
01699 {
01700 case ERROR_MARK:
01701 case IDENTIFIER_NODE:
01702 case INTEGER_CST:
01703 case REAL_CST:
01704 case VECTOR_CST:
01705 case STRING_CST:
01706 case REAL_TYPE:
01707 case COMPLEX_TYPE:
01708 case VECTOR_TYPE:
01709 case VOID_TYPE:
01710 case BOOLEAN_TYPE:
01711 case UNION_TYPE:
01712 case ENUMERAL_TYPE:
01713 case BLOCK:
01714 case RECORD_TYPE:
01715 case CHAR_TYPE:
01716
01717
01718 break;
01719
01720 case POINTER_TYPE:
01721 case REFERENCE_TYPE:
01722 WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
01723 break;
01724
01725 case TREE_LIST:
01726 WALK_SUBTREE (TREE_VALUE (*tp));
01727 WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
01728 break;
01729
01730 case TREE_VEC:
01731 {
01732 int len = TREE_VEC_LENGTH (*tp);
01733
01734 if (len == 0)
01735 break;
01736
01737
01738 while (--len)
01739 WALK_SUBTREE (TREE_VEC_ELT (*tp, len));
01740
01741
01742 WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0));
01743 }
01744
01745 case COMPLEX_CST:
01746 WALK_SUBTREE (TREE_REALPART (*tp));
01747 WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp));
01748
01749 case CONSTRUCTOR:
01750 WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp));
01751
01752 case METHOD_TYPE:
01753 WALK_SUBTREE (TYPE_METHOD_BASETYPE (*tp));
01754
01755
01756 case FUNCTION_TYPE:
01757 WALK_SUBTREE (TREE_TYPE (*tp));
01758 {
01759 tree arg = TYPE_ARG_TYPES (*tp);
01760
01761
01762 for (; arg; arg = TREE_CHAIN (arg))
01763 WALK_SUBTREE (TREE_VALUE (arg));
01764 }
01765 break;
01766
01767 case ARRAY_TYPE:
01768 WALK_SUBTREE (TREE_TYPE (*tp));
01769 WALK_SUBTREE_TAIL (TYPE_DOMAIN (*tp));
01770
01771 case INTEGER_TYPE:
01772 WALK_SUBTREE (TYPE_MIN_VALUE (*tp));
01773 WALK_SUBTREE_TAIL (TYPE_MAX_VALUE (*tp));
01774
01775 case OFFSET_TYPE:
01776 WALK_SUBTREE (TREE_TYPE (*tp));
01777 WALK_SUBTREE_TAIL (TYPE_OFFSET_BASETYPE (*tp));
01778
01779 #ifdef INLINER_FOR_JAVA
01780 case EXIT_BLOCK_EXPR:
01781 WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 1));
01782
01783 case SAVE_EXPR:
01784 WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
01785 #endif
01786
01787 default:
01788 abort ();
01789 }
01790
01791
01792 return NULL_TREE;
01793
01794 #undef WALK_SUBTREE
01795 #undef WALK_SUBTREE_TAIL
01796 }
01797
01798
01799
01800
01801 tree
01802 walk_tree_without_duplicates (tp, func, data)
01803 tree *tp;
01804 walk_tree_fn func;
01805 void *data;
01806 {
01807 tree result;
01808 htab_t htab;
01809
01810 htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
01811 result = walk_tree (tp, func, data, htab);
01812 htab_delete (htab);
01813 return result;
01814 }
01815
01816
01817
01818 tree
01819 copy_tree_r (tp, walk_subtrees, data)
01820 tree *tp;
01821 int *walk_subtrees;
01822 void *data ATTRIBUTE_UNUSED;
01823 {
01824 enum tree_code code = TREE_CODE (*tp);
01825
01826
01827 if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
01828 || TREE_CODE_CLASS (code) == 'r'
01829 || TREE_CODE_CLASS (code) == 'c'
01830 || TREE_CODE_CLASS (code) == 's'
01831 || code == TREE_LIST
01832 || code == TREE_VEC
01833 || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp))
01834 {
01835
01836
01837 tree chain = TREE_CHAIN (*tp);
01838
01839
01840 *tp = copy_node (*tp);
01841
01842
01843
01844 if (code == PARM_DECL || code == TREE_LIST
01845 #ifndef INLINER_FOR_JAVA
01846 || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp)
01847 || statement_code_p (code))
01848 TREE_CHAIN (*tp) = chain;
01849
01850
01851
01852 if (TREE_CODE (*tp) == SCOPE_STMT)
01853 SCOPE_STMT_BLOCK (*tp) = NULL_TREE;
01854 #else
01855 || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp))
01856 TREE_CHAIN (*tp) = chain;
01857 #endif
01858 }
01859 else if (TREE_CODE_CLASS (code) == 't' && !variably_modified_type_p (*tp))
01860
01861 *walk_subtrees = 0;
01862
01863 return NULL_TREE;
01864 }
01865
01866
01867
01868
01869
01870
01871 void
01872 remap_save_expr (tp, st_, fn, walk_subtrees)
01873 tree *tp;
01874 void *st_;
01875 tree fn;
01876 int *walk_subtrees;
01877 {
01878 splay_tree st = (splay_tree) st_;
01879 splay_tree_node n;
01880
01881
01882 n = splay_tree_lookup (st, (splay_tree_key) *tp);
01883
01884
01885 if (!n)
01886 {
01887 tree t = copy_node (*tp);
01888
01889
01890
01891 SAVE_EXPR_CONTEXT (t) = fn;
01892
01893 SAVE_EXPR_RTL (t) = NULL_RTX;
01894
01895 n = splay_tree_insert (st,
01896 (splay_tree_key) *tp,
01897 (splay_tree_value) t);
01898
01899 splay_tree_insert (st, (splay_tree_key) t,
01900 (splay_tree_value) error_mark_node);
01901 }
01902 else
01903
01904
01905 *walk_subtrees = 0;
01906
01907
01908 *tp = (tree) n->value;
01909 }
01910
01911 #ifdef INLINER_FOR_JAVA
01912
01913
01914
01915 static tree
01916 add_stmt_to_compound (existing, type, stmt)
01917 tree existing, type, stmt;
01918 {
01919 if (!stmt)
01920 return existing;
01921 else if (existing)
01922 return build (COMPOUND_EXPR, type, existing, stmt);
01923 else
01924 return stmt;
01925 }
01926
01927 #endif