00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "tree.h"
00026 #include "rtl.h"
00027 #include "tm_p.h"
00028 #include "function.h"
00029 #include "tree-dump.h"
00030 #include "tree-inline.h"
00031 #include "tree-gimple.h"
00032 #include "tree-iterator.h"
00033 #include "tree-flow.h"
00034 #include "cgraph.h"
00035 #include "expr.h"
00036 #include "langhooks.h"
00037 #include "ggc.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 struct var_map_elt
00081 {
00082 tree old;
00083 tree new;
00084 };
00085
00086 struct nesting_info
00087 {
00088 struct nesting_info *outer;
00089 struct nesting_info *inner;
00090 struct nesting_info *next;
00091
00092 htab_t var_map;
00093 tree context;
00094 tree new_local_var_chain;
00095 tree frame_type;
00096 tree frame_decl;
00097 tree chain_field;
00098 tree chain_decl;
00099 tree nl_goto_field;
00100
00101 bool any_parm_remapped;
00102 bool any_tramp_created;
00103 };
00104
00105
00106
00107
00108 static hashval_t
00109 var_map_hash (const void *x)
00110 {
00111 const struct var_map_elt *a = x;
00112 return htab_hash_pointer (a->old);
00113 }
00114
00115 static int
00116 var_map_eq (const void *x, const void *y)
00117 {
00118 const struct var_map_elt *a = x;
00119 const struct var_map_elt *b = y;
00120 return a->old == b->old;
00121 }
00122
00123
00124
00125 #define create_tmp_var cant_use_create_tmp_var_here_dummy
00126
00127
00128
00129
00130 static tree
00131 create_tmp_var_for (struct nesting_info *info, tree type, const char *prefix)
00132 {
00133 tree tmp_var;
00134
00135
00136
00137
00138 gcc_assert (!TREE_ADDRESSABLE (type));
00139 gcc_assert (!TYPE_SIZE_UNIT (type)
00140 || TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST);
00141
00142 tmp_var = create_tmp_var_raw (type, prefix);
00143 DECL_CONTEXT (tmp_var) = info->context;
00144 TREE_CHAIN (tmp_var) = info->new_local_var_chain;
00145 DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1;
00146 info->new_local_var_chain = tmp_var;
00147
00148 return tmp_var;
00149 }
00150
00151
00152
00153 tree
00154 build_addr (tree exp)
00155 {
00156 tree base = exp;
00157
00158 while (handled_component_p (base))
00159 base = TREE_OPERAND (base, 0);
00160
00161 if (DECL_P (base))
00162 TREE_ADDRESSABLE (base) = 1;
00163
00164 return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
00165 }
00166
00167
00168
00169 static void
00170 insert_field_into_struct (tree type, tree field)
00171 {
00172 tree *p;
00173
00174 DECL_CONTEXT (field) = type;
00175
00176 for (p = &TYPE_FIELDS (type); *p ; p = &TREE_CHAIN (*p))
00177 if (DECL_ALIGN (field) >= DECL_ALIGN (*p))
00178 break;
00179
00180 TREE_CHAIN (field) = *p;
00181 *p = field;
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191 static tree
00192 get_frame_type (struct nesting_info *info)
00193 {
00194 tree type = info->frame_type;
00195 if (!type)
00196 {
00197 char *name;
00198
00199 type = make_node (RECORD_TYPE);
00200
00201 name = concat ("FRAME.",
00202 IDENTIFIER_POINTER (DECL_NAME (info->context)),
00203 NULL);
00204 TYPE_NAME (type) = get_identifier (name);
00205 free (name);
00206
00207 info->frame_type = type;
00208 info->frame_decl = create_tmp_var_for (info, type, "FRAME");
00209 }
00210 return type;
00211 }
00212
00213
00214
00215
00216 static bool
00217 use_pointer_in_frame (tree decl)
00218 {
00219 if (TREE_CODE (decl) == PARM_DECL)
00220 {
00221
00222
00223
00224 return AGGREGATE_TYPE_P (TREE_TYPE (decl));
00225 }
00226 else
00227 {
00228
00229 return DECL_SIZE (decl) == NULL || !TREE_CONSTANT (DECL_SIZE (decl));
00230 }
00231 }
00232
00233
00234
00235
00236 static tree
00237 lookup_field_for_decl (struct nesting_info *info, tree decl,
00238 enum insert_option insert)
00239 {
00240 struct var_map_elt *elt, dummy;
00241 void **slot;
00242 tree field;
00243
00244 dummy.old = decl;
00245 slot = htab_find_slot (info->var_map, &dummy, insert);
00246 if (!slot)
00247 {
00248 gcc_assert (insert != INSERT);
00249 return NULL;
00250 }
00251 elt = *slot;
00252
00253 if (!elt && insert == INSERT)
00254 {
00255 field = make_node (FIELD_DECL);
00256 DECL_NAME (field) = DECL_NAME (decl);
00257
00258 if (use_pointer_in_frame (decl))
00259 {
00260 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
00261 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
00262 DECL_NONADDRESSABLE_P (field) = 1;
00263 }
00264 else
00265 {
00266 TREE_TYPE (field) = TREE_TYPE (decl);
00267 DECL_SOURCE_LOCATION (field) = DECL_SOURCE_LOCATION (decl);
00268 DECL_ALIGN (field) = DECL_ALIGN (decl);
00269 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (decl);
00270 TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (decl);
00271 DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (decl);
00272 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl);
00273 }
00274
00275 insert_field_into_struct (get_frame_type (info), field);
00276
00277 elt = xmalloc (sizeof (*elt));
00278 elt->old = decl;
00279 elt->new = field;
00280 *slot = elt;
00281
00282 if (TREE_CODE (decl) == PARM_DECL)
00283 info->any_parm_remapped = true;
00284 }
00285 else
00286 field = elt ? elt->new : NULL;
00287
00288 return field;
00289 }
00290
00291
00292
00293
00294 static tree
00295 get_chain_decl (struct nesting_info *info)
00296 {
00297 tree decl = info->chain_decl;
00298 if (!decl)
00299 {
00300 tree type;
00301
00302 type = get_frame_type (info->outer);
00303 type = build_pointer_type (type);
00304
00305
00306
00307
00308
00309
00310
00311 decl = build_decl (PARM_DECL, create_tmp_var_name ("CHAIN"), type);
00312 DECL_ARTIFICIAL (decl) = 1;
00313 DECL_IGNORED_P (decl) = 1;
00314 TREE_USED (decl) = 1;
00315 DECL_CONTEXT (decl) = info->context;
00316 DECL_ARG_TYPE (decl) = type;
00317
00318
00319
00320 TREE_READONLY (decl) = 1;
00321
00322 info->chain_decl = decl;
00323 }
00324 return decl;
00325 }
00326
00327
00328
00329
00330
00331 static tree
00332 get_chain_field (struct nesting_info *info)
00333 {
00334 tree field = info->chain_field;
00335 if (!field)
00336 {
00337 tree type = build_pointer_type (get_frame_type (info->outer));
00338
00339 field = make_node (FIELD_DECL);
00340 DECL_NAME (field) = get_identifier ("__chain");
00341 TREE_TYPE (field) = type;
00342 DECL_ALIGN (field) = TYPE_ALIGN (type);
00343 DECL_NONADDRESSABLE_P (field) = 1;
00344
00345 insert_field_into_struct (get_frame_type (info), field);
00346
00347 info->chain_field = field;
00348 }
00349 return field;
00350 }
00351
00352
00353
00354
00355 static tree
00356 init_tmp_var (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi)
00357 {
00358 tree t, stmt;
00359
00360 t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
00361 stmt = build (MODIFY_EXPR, TREE_TYPE (t), t, exp);
00362 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
00363 tsi_link_before (tsi, stmt, TSI_SAME_STMT);
00364
00365 return t;
00366 }
00367
00368
00369
00370 static tree
00371 tsi_gimplify_val (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi)
00372 {
00373 if (is_gimple_val (exp))
00374 return exp;
00375 else
00376 return init_tmp_var (info, exp, tsi);
00377 }
00378
00379
00380
00381
00382 static tree
00383 save_tmp_var (struct nesting_info *info, tree exp,
00384 tree_stmt_iterator *tsi)
00385 {
00386 tree t, stmt;
00387
00388 t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
00389 stmt = build (MODIFY_EXPR, TREE_TYPE (t), exp, t);
00390 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
00391 tsi_link_after (tsi, stmt, TSI_SAME_STMT);
00392
00393 return t;
00394 }
00395
00396
00397
00398 static GTY(()) tree trampoline_type;
00399
00400 static tree
00401 get_trampoline_type (void)
00402 {
00403 tree record, t;
00404 unsigned align, size;
00405
00406 if (trampoline_type)
00407 return trampoline_type;
00408
00409 align = TRAMPOLINE_ALIGNMENT;
00410 size = TRAMPOLINE_SIZE;
00411
00412
00413
00414 if (align > STACK_BOUNDARY)
00415 {
00416 size += ((align/BITS_PER_UNIT) - 1) & -(STACK_BOUNDARY/BITS_PER_UNIT);
00417 align = STACK_BOUNDARY;
00418 }
00419
00420 t = build_index_type (build_int_cst (NULL_TREE, size - 1));
00421 t = build_array_type (char_type_node, t);
00422 t = build_decl (FIELD_DECL, get_identifier ("__data"), t);
00423 DECL_ALIGN (t) = align;
00424 DECL_USER_ALIGN (t) = 1;
00425
00426 record = make_node (RECORD_TYPE);
00427 TYPE_NAME (record) = get_identifier ("__builtin_trampoline");
00428 TYPE_FIELDS (record) = t;
00429 layout_type (record);
00430
00431 return record;
00432 }
00433
00434
00435
00436
00437 static tree
00438 lookup_tramp_for_decl (struct nesting_info *info, tree decl,
00439 enum insert_option insert)
00440 {
00441 struct var_map_elt *elt, dummy;
00442 void **slot;
00443 tree field;
00444
00445 dummy.old = decl;
00446 slot = htab_find_slot (info->var_map, &dummy, insert);
00447 if (!slot)
00448 {
00449 gcc_assert (insert != INSERT);
00450 return NULL;
00451 }
00452 elt = *slot;
00453
00454 if (!elt && insert == INSERT)
00455 {
00456 field = make_node (FIELD_DECL);
00457 DECL_NAME (field) = DECL_NAME (decl);
00458 TREE_TYPE (field) = get_trampoline_type ();
00459 TREE_ADDRESSABLE (field) = 1;
00460
00461 insert_field_into_struct (get_frame_type (info), field);
00462
00463 elt = xmalloc (sizeof (*elt));
00464 elt->old = decl;
00465 elt->new = field;
00466 *slot = elt;
00467
00468 info->any_tramp_created = true;
00469 }
00470 else
00471 field = elt ? elt->new : NULL;
00472
00473 return field;
00474 }
00475
00476
00477
00478
00479
00480 static tree
00481 get_nl_goto_field (struct nesting_info *info)
00482 {
00483 tree field = info->nl_goto_field;
00484 if (!field)
00485 {
00486 unsigned size;
00487 tree type;
00488
00489
00490
00491
00492
00493 if (Pmode == ptr_mode)
00494 type = ptr_type_node;
00495 else
00496 type = lang_hooks.types.type_for_mode (Pmode, 1);
00497
00498 size = GET_MODE_SIZE (STACK_SAVEAREA_MODE (SAVE_NONLOCAL));
00499 size = size / GET_MODE_SIZE (Pmode);
00500 size = size + 1;
00501
00502 type = build_array_type
00503 (type, build_index_type (build_int_cst (NULL_TREE, size)));
00504
00505 field = make_node (FIELD_DECL);
00506 DECL_NAME (field) = get_identifier ("__nl_goto_buf");
00507 TREE_TYPE (field) = type;
00508 DECL_ALIGN (field) = TYPE_ALIGN (type);
00509 TREE_ADDRESSABLE (field) = 1;
00510
00511 insert_field_into_struct (get_frame_type (info), field);
00512
00513 info->nl_goto_field = field;
00514 }
00515
00516 return field;
00517 }
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 struct walk_stmt_info
00532 {
00533 walk_tree_fn callback;
00534 tree_stmt_iterator tsi;
00535 struct nesting_info *info;
00536 bool val_only;
00537 bool is_lhs;
00538 bool changed;
00539 };
00540
00541
00542
00543 static void
00544 walk_stmts (struct walk_stmt_info *wi, tree *tp)
00545 {
00546 tree t = *tp;
00547 if (!t)
00548 return;
00549
00550 switch (TREE_CODE (t))
00551 {
00552 case STATEMENT_LIST:
00553 {
00554 tree_stmt_iterator i;
00555 for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
00556 {
00557 wi->tsi = i;
00558 walk_stmts (wi, tsi_stmt_ptr (i));
00559 }
00560 }
00561 break;
00562
00563 case COND_EXPR:
00564 walk_tree (&COND_EXPR_COND (t), wi->callback, wi, NULL);
00565 walk_stmts (wi, &COND_EXPR_THEN (t));
00566 walk_stmts (wi, &COND_EXPR_ELSE (t));
00567 break;
00568 case CATCH_EXPR:
00569 walk_stmts (wi, &CATCH_BODY (t));
00570 break;
00571 case EH_FILTER_EXPR:
00572 walk_stmts (wi, &EH_FILTER_FAILURE (t));
00573 break;
00574 case TRY_CATCH_EXPR:
00575 case TRY_FINALLY_EXPR:
00576 walk_stmts (wi, &TREE_OPERAND (t, 0));
00577 walk_stmts (wi, &TREE_OPERAND (t, 1));
00578 break;
00579 case BIND_EXPR:
00580 walk_stmts (wi, &BIND_EXPR_BODY (t));
00581 break;
00582
00583 case RETURN_EXPR:
00584 walk_stmts (wi, &TREE_OPERAND (t, 0));
00585 break;
00586
00587 case MODIFY_EXPR:
00588
00589 wi->val_only = !is_gimple_formal_tmp_var (TREE_OPERAND (t, 0));
00590 walk_tree (&TREE_OPERAND (t, 1), wi->callback, wi, NULL);
00591
00592
00593
00594 wi->val_only = !is_gimple_mem_rhs (TREE_OPERAND (t, 1));
00595 wi->is_lhs = true;
00596 walk_tree (&TREE_OPERAND (t, 0), wi->callback, wi, NULL);
00597
00598 wi->val_only = true;
00599 wi->is_lhs = false;
00600 break;
00601
00602 default:
00603 wi->val_only = true;
00604 walk_tree (tp, wi->callback, wi, NULL);
00605 break;
00606 }
00607 }
00608
00609
00610
00611 static void
00612 walk_function (walk_tree_fn callback, struct nesting_info *info)
00613 {
00614 struct walk_stmt_info wi;
00615
00616 memset (&wi, 0, sizeof (wi));
00617 wi.callback = callback;
00618 wi.info = info;
00619 wi.val_only = true;
00620
00621 walk_stmts (&wi, &DECL_SAVED_TREE (info->context));
00622 }
00623
00624
00625
00626 static void
00627 walk_all_functions (walk_tree_fn callback, struct nesting_info *root)
00628 {
00629 do
00630 {
00631 if (root->inner)
00632 walk_all_functions (callback, root->inner);
00633 walk_function (callback, root);
00634 root = root->next;
00635 }
00636 while (root);
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662 static bool
00663 check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl)
00664 {
00665 struct cgraph_node *cgn = cgraph_node (fndecl);
00666 tree arg;
00667
00668 for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
00669 {
00670 for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = TREE_CHAIN (arg))
00671 if (variably_modified_type_p (TREE_TYPE (arg), 0), orig_fndecl)
00672 return true;
00673
00674 if (check_for_nested_with_variably_modified (cgn->decl, orig_fndecl))
00675 return true;
00676 }
00677
00678 return false;
00679 }
00680
00681
00682
00683
00684 static struct nesting_info *
00685 create_nesting_tree (struct cgraph_node *cgn)
00686 {
00687 struct nesting_info *info = xcalloc (1, sizeof (*info));
00688 info->var_map = htab_create (7, var_map_hash, var_map_eq, free);
00689 info->context = cgn->decl;
00690
00691 for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
00692 {
00693 struct nesting_info *sub = create_nesting_tree (cgn);
00694 sub->outer = info;
00695 sub->next = info->inner;
00696 info->inner = sub;
00697 }
00698
00699
00700
00701 if (check_for_nested_with_variably_modified (info->context, info->context))
00702 DECL_UNINLINABLE (info->context) = true;
00703
00704 return info;
00705 }
00706
00707
00708
00709
00710 static tree
00711 get_static_chain (struct nesting_info *info, tree target_context,
00712 tree_stmt_iterator *tsi)
00713 {
00714 struct nesting_info *i;
00715 tree x;
00716
00717 if (info->context == target_context)
00718 {
00719 x = build_addr (info->frame_decl);
00720 }
00721 else
00722 {
00723 x = get_chain_decl (info);
00724
00725 for (i = info->outer; i->context != target_context; i = i->outer)
00726 {
00727 tree field = get_chain_field (i);
00728
00729 x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
00730 x = build (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
00731 x = init_tmp_var (info, x, tsi);
00732 }
00733 }
00734
00735 return x;
00736 }
00737
00738
00739
00740
00741
00742 static tree
00743 get_frame_field (struct nesting_info *info, tree target_context,
00744 tree field, tree_stmt_iterator *tsi)
00745 {
00746 struct nesting_info *i;
00747 tree x;
00748
00749 if (info->context == target_context)
00750 {
00751
00752 (void) get_frame_type (info);
00753 x = info->frame_decl;
00754 }
00755 else
00756 {
00757 x = get_chain_decl (info);
00758
00759 for (i = info->outer; i->context != target_context; i = i->outer)
00760 {
00761 tree field = get_chain_field (i);
00762
00763 x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
00764 x = build (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
00765 x = init_tmp_var (info, x, tsi);
00766 }
00767
00768 x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
00769 }
00770
00771 x = build (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
00772 return x;
00773 }
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783 static tree
00784 convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
00785 {
00786 struct walk_stmt_info *wi = data;
00787 struct nesting_info *info = wi->info;
00788 tree t = *tp;
00789
00790 *walk_subtrees = 0;
00791 switch (TREE_CODE (t))
00792 {
00793 case VAR_DECL:
00794
00795 if (TREE_STATIC (t) || DECL_EXTERNAL (t))
00796 break;
00797
00798
00799 case PARM_DECL:
00800 if (decl_function_context (t) != info->context)
00801 {
00802 tree target_context = decl_function_context (t);
00803 struct nesting_info *i;
00804 tree x;
00805 wi->changed = true;
00806
00807 for (i = info->outer; i->context != target_context; i = i->outer)
00808 continue;
00809 x = lookup_field_for_decl (i, t, INSERT);
00810 x = get_frame_field (info, target_context, x, &wi->tsi);
00811 if (use_pointer_in_frame (t))
00812 {
00813 x = init_tmp_var (info, x, &wi->tsi);
00814 x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
00815 }
00816
00817 if (wi->val_only)
00818 {
00819 if (wi->is_lhs)
00820 x = save_tmp_var (info, x, &wi->tsi);
00821 else
00822 x = init_tmp_var (info, x, &wi->tsi);
00823 }
00824
00825 *tp = x;
00826 }
00827 break;
00828
00829 case GOTO_EXPR:
00830
00831 if (TREE_CODE (GOTO_DESTINATION (t)) != LABEL_DECL)
00832 {
00833 *walk_subtrees = 1;
00834 wi->val_only = true;
00835 wi->is_lhs = false;
00836 }
00837 break;
00838
00839 case LABEL_DECL:
00840
00841
00842
00843
00844 if (decl_function_context (t) != info->context)
00845 FORCED_LABEL (t) = 1;
00846 break;
00847
00848 case ADDR_EXPR:
00849 {
00850 bool save_val_only = wi->val_only;
00851
00852 wi->val_only = false;
00853 wi->is_lhs = false;
00854 wi->changed = false;
00855 walk_tree (&TREE_OPERAND (t, 0), convert_nonlocal_reference, wi, NULL);
00856 wi->val_only = true;
00857
00858 if (wi->changed)
00859 {
00860
00861
00862 recompute_tree_invarant_for_addr_expr (t);
00863
00864
00865
00866
00867 if (save_val_only)
00868 *tp = tsi_gimplify_val (wi->info, t, &wi->tsi);
00869 }
00870 }
00871 break;
00872
00873 case REALPART_EXPR:
00874 case IMAGPART_EXPR:
00875 case COMPONENT_REF:
00876 case ARRAY_REF:
00877 case ARRAY_RANGE_REF:
00878 case BIT_FIELD_REF:
00879
00880
00881
00882 wi->val_only = true;
00883 wi->is_lhs = false;
00884 for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp)
00885 {
00886 if (TREE_CODE (t) == COMPONENT_REF)
00887 walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi,
00888 NULL);
00889 else if (TREE_CODE (t) == ARRAY_REF
00890 || TREE_CODE (t) == ARRAY_RANGE_REF)
00891 {
00892 walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference, wi,
00893 NULL);
00894 walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi,
00895 NULL);
00896 walk_tree (&TREE_OPERAND (t, 3), convert_nonlocal_reference, wi,
00897 NULL);
00898 }
00899 else if (TREE_CODE (t) == BIT_FIELD_REF)
00900 {
00901 walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference, wi,
00902 NULL);
00903 walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi,
00904 NULL);
00905 }
00906 }
00907 wi->val_only = false;
00908 walk_tree (tp, convert_nonlocal_reference, wi, NULL);
00909 break;
00910
00911 default:
00912 if (!IS_TYPE_OR_DECL_P (t))
00913 {
00914 *walk_subtrees = 1;
00915 wi->val_only = true;
00916 wi->is_lhs = false;
00917 }
00918 break;
00919 }
00920
00921 return NULL_TREE;
00922 }
00923
00924
00925
00926
00927
00928 static tree
00929 convert_local_reference (tree *tp, int *walk_subtrees, void *data)
00930 {
00931 struct walk_stmt_info *wi = data;
00932 struct nesting_info *info = wi->info;
00933 tree t = *tp, field, x;
00934 bool save_val_only;
00935
00936 *walk_subtrees = 0;
00937 switch (TREE_CODE (t))
00938 {
00939 case VAR_DECL:
00940
00941 if (TREE_STATIC (t) || DECL_EXTERNAL (t))
00942 break;
00943
00944
00945 case PARM_DECL:
00946 if (decl_function_context (t) == info->context)
00947 {
00948
00949
00950 if (use_pointer_in_frame (t))
00951 break;
00952
00953
00954
00955 field = lookup_field_for_decl (info, t, NO_INSERT);
00956 if (!field)
00957 break;
00958 wi->changed = true;
00959
00960 x = get_frame_field (info, info->context, field, &wi->tsi);
00961
00962 if (wi->val_only)
00963 {
00964 if (wi->is_lhs)
00965 x = save_tmp_var (info, x, &wi->tsi);
00966 else
00967 x = init_tmp_var (info, x, &wi->tsi);
00968 }
00969
00970 *tp = x;
00971 }
00972 break;
00973
00974 case ADDR_EXPR:
00975 save_val_only = wi->val_only;
00976 wi->val_only = false;
00977 wi->is_lhs = false;
00978 wi->changed = false;
00979 walk_tree (&TREE_OPERAND (t, 0), convert_local_reference, wi, NULL);
00980 wi->val_only = save_val_only;
00981
00982
00983 if (wi->changed)
00984 {
00985 tree save_context;
00986
00987
00988 TREE_ADDRESSABLE (info->frame_decl) = 1;
00989
00990 save_context = current_function_decl;
00991 current_function_decl = info->context;
00992 recompute_tree_invarant_for_addr_expr (t);
00993 current_function_decl = save_context;
00994
00995
00996
00997 if (save_val_only)
00998 *tp = tsi_gimplify_val (wi->info, t, &wi->tsi);
00999 }
01000 break;
01001
01002 case REALPART_EXPR:
01003 case IMAGPART_EXPR:
01004 case COMPONENT_REF:
01005 case ARRAY_REF:
01006 case ARRAY_RANGE_REF:
01007 case BIT_FIELD_REF:
01008
01009
01010
01011 save_val_only = wi->val_only;
01012 wi->val_only = true;
01013 wi->is_lhs = false;
01014 for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp)
01015 {
01016 if (TREE_CODE (t) == COMPONENT_REF)
01017 walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi,
01018 NULL);
01019 else if (TREE_CODE (t) == ARRAY_REF
01020 || TREE_CODE (t) == ARRAY_RANGE_REF)
01021 {
01022 walk_tree (&TREE_OPERAND (t, 1), convert_local_reference, wi,
01023 NULL);
01024 walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi,
01025 NULL);
01026 walk_tree (&TREE_OPERAND (t, 3), convert_local_reference, wi,
01027 NULL);
01028 }
01029 else if (TREE_CODE (t) == BIT_FIELD_REF)
01030 {
01031 walk_tree (&TREE_OPERAND (t, 1), convert_local_reference, wi,
01032 NULL);
01033 walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi,
01034 NULL);
01035 }
01036 }
01037 wi->val_only = false;
01038 walk_tree (tp, convert_local_reference, wi, NULL);
01039 wi->val_only = save_val_only;
01040 break;
01041
01042 default:
01043 if (!IS_TYPE_OR_DECL_P (t))
01044 {
01045 *walk_subtrees = 1;
01046 wi->val_only = true;
01047 wi->is_lhs = false;
01048 }
01049 break;
01050 }
01051
01052 return NULL_TREE;
01053 }
01054
01055
01056
01057
01058
01059 static tree
01060 convert_nl_goto_reference (tree *tp, int *walk_subtrees, void *data)
01061 {
01062 struct walk_stmt_info *wi = data;
01063 struct nesting_info *info = wi->info, *i;
01064 tree t = *tp, label, new_label, target_context, x, arg, field;
01065 struct var_map_elt *elt;
01066 void **slot;
01067
01068 *walk_subtrees = 0;
01069 if (TREE_CODE (t) != GOTO_EXPR)
01070 return NULL_TREE;
01071 label = GOTO_DESTINATION (t);
01072 if (TREE_CODE (label) != LABEL_DECL)
01073 return NULL_TREE;
01074 target_context = decl_function_context (label);
01075 if (target_context == info->context)
01076 return NULL_TREE;
01077
01078 for (i = info->outer; target_context != i->context; i = i->outer)
01079 continue;
01080
01081
01082
01083
01084
01085
01086
01087 new_label = create_artificial_label ();
01088 DECL_NONLOCAL (new_label) = 1;
01089
01090
01091
01092 elt = xmalloc (sizeof (*elt));
01093 elt->old = label;
01094 elt->new = new_label;
01095 slot = htab_find_slot (i->var_map, elt, INSERT);
01096 *slot = elt;
01097
01098
01099 field = get_nl_goto_field (i);
01100 x = get_frame_field (info, target_context, field, &wi->tsi);
01101 x = build_addr (x);
01102 x = tsi_gimplify_val (info, x, &wi->tsi);
01103 arg = tree_cons (NULL, x, NULL);
01104 x = build_addr (new_label);
01105 arg = tree_cons (NULL, x, arg);
01106 x = implicit_built_in_decls[BUILT_IN_NONLOCAL_GOTO];
01107 x = build_function_call_expr (x, arg);
01108
01109 SET_EXPR_LOCUS (x, EXPR_LOCUS (tsi_stmt (wi->tsi)));
01110 *tsi_stmt_ptr (wi->tsi) = x;
01111
01112 return NULL_TREE;
01113 }
01114
01115
01116
01117
01118
01119
01120
01121 static tree
01122 convert_nl_goto_receiver (tree *tp, int *walk_subtrees, void *data)
01123 {
01124 struct walk_stmt_info *wi = data;
01125 struct nesting_info *info = wi->info;
01126 tree t = *tp, label, new_label, x;
01127 struct var_map_elt *elt, dummy;
01128 tree_stmt_iterator tmp_tsi;
01129
01130 *walk_subtrees = 0;
01131 if (TREE_CODE (t) != LABEL_EXPR)
01132 return NULL_TREE;
01133 label = LABEL_EXPR_LABEL (t);
01134
01135 dummy.old = label;
01136 elt = htab_find (info->var_map, &dummy);
01137 if (!elt)
01138 return NULL_TREE;
01139 new_label = elt->new;
01140
01141
01142
01143 tmp_tsi = wi->tsi;
01144 tsi_prev (&tmp_tsi);
01145 if (tsi_end_p (tmp_tsi) || block_may_fallthru (tsi_stmt (tmp_tsi)))
01146 {
01147 x = build1 (GOTO_EXPR, void_type_node, label);
01148 tsi_link_before (&wi->tsi, x, TSI_SAME_STMT);
01149 }
01150 x = build1 (LABEL_EXPR, void_type_node, new_label);
01151 tsi_link_before (&wi->tsi, x, TSI_SAME_STMT);
01152
01153 return NULL_TREE;
01154 }
01155
01156
01157
01158
01159
01160 static tree
01161 convert_tramp_reference (tree *tp, int *walk_subtrees, void *data)
01162 {
01163 struct walk_stmt_info *wi = data;
01164 struct nesting_info *info = wi->info, *i;
01165 tree t = *tp, decl, target_context, x, arg;
01166
01167 *walk_subtrees = 0;
01168 switch (TREE_CODE (t))
01169 {
01170 case ADDR_EXPR:
01171
01172
01173
01174
01175
01176
01177 decl = TREE_OPERAND (t, 0);
01178 if (TREE_CODE (decl) != FUNCTION_DECL)
01179 break;
01180
01181
01182 target_context = decl_function_context (decl);
01183 if (!target_context)
01184 break;
01185
01186
01187
01188 if (DECL_NO_STATIC_CHAIN (decl))
01189 break;
01190
01191
01192
01193 for (i = info; i->context != target_context; i = i->outer)
01194 continue;
01195 x = lookup_tramp_for_decl (i, decl, INSERT);
01196
01197
01198 x = get_frame_field (info, target_context, x, &wi->tsi);
01199 x = build_addr (x);
01200 x = tsi_gimplify_val (info, x, &wi->tsi);
01201 arg = tree_cons (NULL, x, NULL);
01202
01203
01204
01205 x = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE];
01206 x = build_function_call_expr (x, arg);
01207 x = init_tmp_var (info, x, &wi->tsi);
01208
01209
01210 x = build1 (NOP_EXPR, TREE_TYPE (t), x);
01211 x = init_tmp_var (info, x, &wi->tsi);
01212
01213 *tp = x;
01214 break;
01215
01216 case CALL_EXPR:
01217
01218
01219 walk_tree (&TREE_OPERAND (t, 1), convert_tramp_reference, wi, NULL);
01220 break;
01221
01222 default:
01223 if (!IS_TYPE_OR_DECL_P (t))
01224 *walk_subtrees = 1;
01225 break;
01226 }
01227
01228 return NULL_TREE;
01229 }
01230
01231
01232
01233
01234
01235 static tree
01236 convert_call_expr (tree *tp, int *walk_subtrees, void *data)
01237 {
01238 struct walk_stmt_info *wi = data;
01239 struct nesting_info *info = wi->info;
01240 tree t = *tp, decl, target_context;
01241
01242 *walk_subtrees = 0;
01243 switch (TREE_CODE (t))
01244 {
01245 case CALL_EXPR:
01246 decl = get_callee_fndecl (t);
01247 if (!decl)
01248 break;
01249 target_context = decl_function_context (decl);
01250 if (target_context && !DECL_NO_STATIC_CHAIN (decl))
01251 TREE_OPERAND (t, 2)
01252 = get_static_chain (info, target_context, &wi->tsi);
01253 break;
01254
01255 case RETURN_EXPR:
01256 case MODIFY_EXPR:
01257 case WITH_SIZE_EXPR:
01258
01259 *walk_subtrees = 1;
01260 break;
01261
01262 default:
01263 break;
01264 }
01265
01266 return NULL_TREE;
01267 }
01268
01269
01270
01271
01272
01273 static void
01274 convert_all_function_calls (struct nesting_info *root)
01275 {
01276 do
01277 {
01278 if (root->inner)
01279 convert_all_function_calls (root->inner);
01280
01281 walk_function (convert_tramp_reference, root);
01282 walk_function (convert_call_expr, root);
01283
01284
01285 if (root->outer && !root->chain_decl && !root->chain_field)
01286 DECL_NO_STATIC_CHAIN (root->context) = 1;
01287 else
01288 gcc_assert (!DECL_NO_STATIC_CHAIN (root->context));
01289
01290 root = root->next;
01291 }
01292 while (root);
01293 }
01294
01295
01296
01297
01298
01299
01300 static void
01301 finalize_nesting_tree_1 (struct nesting_info *root)
01302 {
01303 tree stmt_list = NULL;
01304 tree context = root->context;
01305 struct function *sf;
01306 struct cgraph_node *node;
01307
01308
01309
01310 if (root->frame_type)
01311 {
01312 layout_type (root->frame_type);
01313 layout_decl (root->frame_decl, 0);
01314 }
01315
01316
01317
01318
01319 if (root->any_parm_remapped)
01320 {
01321 tree p;
01322 for (p = DECL_ARGUMENTS (context); p ; p = TREE_CHAIN (p))
01323 {
01324 tree field, x, y;
01325
01326 field = lookup_field_for_decl (root, p, NO_INSERT);
01327 if (!field)
01328 continue;
01329
01330 if (use_pointer_in_frame (p))
01331 x = build_addr (p);
01332 else
01333 x = p;
01334
01335 y = build (COMPONENT_REF, TREE_TYPE (field),
01336 root->frame_decl, field, NULL_TREE);
01337 x = build (MODIFY_EXPR, TREE_TYPE (field), y, x);
01338 append_to_statement_list (x, &stmt_list);
01339 }
01340 }
01341
01342
01343
01344 if (root->chain_field)
01345 {
01346 tree x = build (COMPONENT_REF, TREE_TYPE (root->chain_field),
01347 root->frame_decl, root->chain_field, NULL_TREE);
01348 x = build (MODIFY_EXPR, TREE_TYPE (x), x, get_chain_decl (root));
01349 append_to_statement_list (x, &stmt_list);
01350 }
01351
01352
01353 if (root->any_tramp_created)
01354 {
01355 struct nesting_info *i;
01356 for (i = root->inner; i ; i = i->next)
01357 {
01358 tree arg, x, field;
01359
01360 field = lookup_tramp_for_decl (root, i->context, NO_INSERT);
01361 if (!field)
01362 continue;
01363
01364 if (DECL_NO_STATIC_CHAIN (i->context))
01365 x = null_pointer_node;
01366 else
01367 x = build_addr (root->frame_decl);
01368 arg = tree_cons (NULL, x, NULL);
01369
01370 x = build_addr (i->context);
01371 arg = tree_cons (NULL, x, arg);
01372
01373 x = build (COMPONENT_REF, TREE_TYPE (field),
01374 root->frame_decl, field, NULL_TREE);
01375 x = build_addr (x);
01376 arg = tree_cons (NULL, x, arg);
01377
01378 x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE];
01379 x = build_function_call_expr (x, arg);
01380
01381 append_to_statement_list (x, &stmt_list);
01382 }
01383 }
01384
01385
01386 if (stmt_list)
01387 {
01388 annotate_all_with_locus (&stmt_list,
01389 DECL_SOURCE_LOCATION (context));
01390 append_to_statement_list (BIND_EXPR_BODY (DECL_SAVED_TREE (context)),
01391 &stmt_list);
01392 BIND_EXPR_BODY (DECL_SAVED_TREE (context)) = stmt_list;
01393 }
01394
01395
01396
01397
01398 sf = DECL_STRUCT_FUNCTION (root->context);
01399 sf->static_chain_decl = root->chain_decl;
01400
01401
01402 if (root->nl_goto_field)
01403 {
01404 sf->nonlocal_goto_save_area
01405 = get_frame_field (root, context, root->nl_goto_field, NULL);
01406 sf->has_nonlocal_label = 1;
01407 }
01408
01409
01410
01411 if (root->new_local_var_chain)
01412 declare_tmp_vars (root->new_local_var_chain,
01413 DECL_SAVED_TREE (root->context));
01414
01415
01416 dump_function (TDI_nested, root->context);
01417 node = cgraph_node (root->context);
01418
01419
01420
01421 if (node->origin)
01422 {
01423 cgraph_unnest_node (cgraph_node (root->context));
01424 cgraph_finalize_function (root->context, true);
01425 }
01426 }
01427
01428 static void
01429 finalize_nesting_tree (struct nesting_info *root)
01430 {
01431 do
01432 {
01433 if (root->inner)
01434 finalize_nesting_tree (root->inner);
01435 finalize_nesting_tree_1 (root);
01436 root = root->next;
01437 }
01438 while (root);
01439 }
01440
01441
01442
01443 static void
01444 free_nesting_tree (struct nesting_info *root)
01445 {
01446 struct nesting_info *next;
01447 do
01448 {
01449 if (root->inner)
01450 free_nesting_tree (root->inner);
01451 htab_delete (root->var_map);
01452 next = root->next;
01453 free (root);
01454 root = next;
01455 }
01456 while (root);
01457 }
01458
01459
01460
01461
01462 void
01463 lower_nested_functions (tree fndecl)
01464 {
01465 struct nesting_info *root;
01466 struct cgraph_node *cgn;
01467
01468
01469 cgn = cgraph_node (fndecl);
01470 if (!cgn->nested)
01471 return;
01472
01473 root = create_nesting_tree (cgn);
01474 walk_all_functions (convert_nonlocal_reference, root);
01475 walk_all_functions (convert_local_reference, root);
01476 walk_all_functions (convert_nl_goto_reference, root);
01477 walk_all_functions (convert_nl_goto_receiver, root);
01478 convert_all_function_calls (root);
01479 finalize_nesting_tree (root);
01480 free_nesting_tree (root);
01481 }
01482
01483 #include "gt-tree-nested.h"