00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "errors.h"
00026 #include "system.h"
00027 #include "coretypes.h"
00028 #include "tm.h"
00029 #include "hard-reg-set.h"
00030 #include "rtl.h"
00031 #include "tree.h"
00032 #include "tm_p.h"
00033 #include "basic-block.h"
00034 #include "flags.h"
00035 #include "function.h"
00036 #include "tree-inline.h"
00037 #include "tree-gimple.h"
00038 #include "tree-flow.h"
00039 #include "tree-mudflap.h"
00040 #include "tree-dump.h"
00041 #include "tree-pass.h"
00042 #include "hashtab.h"
00043 #include "diagnostic.h"
00044 #include <demangle.h>
00045 #include "langhooks.h"
00046 #include "ggc.h"
00047 #include "cgraph.h"
00048
00049
00050
00051
00052 static tree mf_build_string (const char *string);
00053 static tree mf_varname_tree (tree);
00054 static tree mf_file_function_line_tree (location_t);
00055
00056
00057 static void mf_decl_cache_locals (void);
00058 static void mf_decl_clear_locals (void);
00059 static void mf_xform_derefs (void);
00060 static void execute_mudflap_function_ops (void);
00061
00062
00063 static void mf_xform_decls (tree, tree);
00064 static tree mx_xfn_xform_decls (tree *, int *, void *);
00065 static void mx_register_decls (tree, tree *);
00066 static void execute_mudflap_function_decls (void);
00067
00068
00069
00070
00071
00072
00073 static tree
00074 mf_build_string (const char *string)
00075 {
00076 size_t len = strlen (string);
00077 tree result = mf_mark (build_string (len + 1, string));
00078
00079 TREE_TYPE (result) = build_array_type
00080 (char_type_node, build_index_type (build_int_cst (NULL_TREE, len)));
00081 TREE_CONSTANT (result) = 1;
00082 TREE_INVARIANT (result) = 1;
00083 TREE_READONLY (result) = 1;
00084 TREE_STATIC (result) = 1;
00085
00086 result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result);
00087
00088 return mf_mark (result);
00089 }
00090
00091
00092
00093
00094
00095
00096 static tree
00097 mf_varname_tree (tree decl)
00098 {
00099 static pretty_printer buf_rec;
00100 static int initialized = 0;
00101 pretty_printer *buf = & buf_rec;
00102 const char *buf_contents;
00103 tree result;
00104
00105 gcc_assert (decl);
00106
00107 if (!initialized)
00108 {
00109 pp_construct (buf, NULL, 0);
00110 initialized = 1;
00111 }
00112 pp_clear_output_area (buf);
00113
00114
00115 {
00116 expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (decl));
00117 const char *sourcefile;
00118 unsigned sourceline = xloc.line;
00119 unsigned sourcecolumn = 0;
00120 #ifdef USE_MAPPED_LOCATION
00121 sourcecolumn = xloc.column;
00122 #endif
00123 sourcefile = xloc.file;
00124 if (sourcefile == NULL && current_function_decl != NULL_TREE)
00125 sourcefile = DECL_SOURCE_FILE (current_function_decl);
00126 if (sourcefile == NULL)
00127 sourcefile = "<unknown file>";
00128
00129 pp_string (buf, sourcefile);
00130
00131 if (sourceline != 0)
00132 {
00133 pp_string (buf, ":");
00134 pp_decimal_int (buf, sourceline);
00135
00136 if (sourcecolumn != 0)
00137 {
00138 pp_string (buf, ":");
00139 pp_decimal_int (buf, sourcecolumn);
00140 }
00141 }
00142 }
00143
00144 if (current_function_decl != NULL_TREE)
00145 {
00146
00147 pp_string (buf, " (");
00148 {
00149 const char *funcname = NULL;
00150 if (DECL_NAME (current_function_decl))
00151 funcname = lang_hooks.decl_printable_name (current_function_decl, 1);
00152 if (funcname == NULL)
00153 funcname = "anonymous fn";
00154
00155 pp_string (buf, funcname);
00156 }
00157 pp_string (buf, ") ");
00158 }
00159 else
00160 pp_string (buf, " ");
00161
00162
00163 {
00164 const char *declname = NULL;
00165
00166 if (DECL_NAME (decl) != NULL)
00167 {
00168 if (strcmp ("GNU C++", lang_hooks.name) == 0)
00169 {
00170
00171
00172 declname = cplus_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)),
00173 DMGL_AUTO | DMGL_VERBOSE);
00174 }
00175 if (declname == NULL)
00176 declname = lang_hooks.decl_printable_name (decl, 3);
00177 }
00178 if (declname == NULL)
00179 declname = "<unnamed variable>";
00180
00181 pp_string (buf, declname);
00182 }
00183
00184
00185 buf_contents = pp_base_formatted_text (buf);
00186 result = mf_build_string (buf_contents);
00187 pp_clear_output_area (buf);
00188
00189 return result;
00190 }
00191
00192
00193
00194
00195 static tree
00196 mf_file_function_line_tree (location_t location)
00197 {
00198 expanded_location xloc = expand_location (location);
00199 const char *file = NULL, *colon, *line, *op, *name, *cp;
00200 char linecolbuf[30];
00201 char *string;
00202 tree result;
00203
00204
00205 file = xloc.file;
00206 if (file == NULL && current_function_decl != NULL_TREE)
00207 file = DECL_SOURCE_FILE (current_function_decl);
00208 if (file == NULL)
00209 file = "<unknown file>";
00210
00211 if (xloc.line > 0)
00212 {
00213 #ifdef USE_MAPPED_LOCATION
00214 if (xloc.column > 0)
00215 sprintf (linecolbuf, "%d:%d", xloc.line, xloc.column);
00216 else
00217 #endif
00218 sprintf (linecolbuf, "%d", xloc.line);
00219 colon = ":";
00220 line = linecolbuf;
00221 }
00222 else
00223 colon = line = "";
00224
00225
00226 name = lang_hooks.decl_printable_name (current_function_decl, 1);
00227 if (name)
00228 {
00229 op = " (";
00230 cp = ")";
00231 }
00232 else
00233 op = name = cp = "";
00234
00235 string = concat (file, colon, line, op, name, cp, NULL);
00236 result = mf_build_string (string);
00237 free (string);
00238
00239 return result;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 static GTY (()) tree mf_uintptr_type;
00251
00252
00253 static GTY (()) tree mf_cache_struct_type;
00254
00255
00256 static GTY (()) tree mf_cache_structptr_type;
00257
00258
00259 static GTY (()) tree mf_cache_array_decl;
00260
00261
00262 static GTY (()) tree mf_cache_shift_decl;
00263
00264
00265 static GTY (()) tree mf_cache_mask_decl;
00266
00267
00268
00269
00270 static GTY (()) tree mf_cache_shift_decl_l;
00271
00272
00273 static GTY (()) tree mf_cache_mask_decl_l;
00274
00275
00276 static GTY (()) tree mf_check_fndecl;
00277
00278
00279 static GTY (()) tree mf_register_fndecl;
00280
00281
00282 static GTY (()) tree mf_unregister_fndecl;
00283
00284
00285 static GTY (()) tree mf_init_fndecl;
00286
00287
00288 static GTY (()) tree mf_set_options_fndecl;
00289
00290
00291
00292
00293 static inline tree
00294 mf_make_builtin (enum tree_code category, const char *name, tree type)
00295 {
00296 tree decl = mf_mark (build_decl (category, get_identifier (name), type));
00297 TREE_PUBLIC (decl) = 1;
00298 DECL_EXTERNAL (decl) = 1;
00299 lang_hooks.decls.pushdecl (decl);
00300 return decl;
00301 }
00302
00303
00304
00305
00306 static inline tree
00307 mf_make_mf_cache_struct_type (tree field_type)
00308 {
00309
00310
00311
00312 tree fieldlo = build_decl (FIELD_DECL, get_identifier ("low"), field_type);
00313 tree fieldhi = build_decl (FIELD_DECL, get_identifier ("high"), field_type);
00314
00315 tree struct_type = make_node (RECORD_TYPE);
00316 DECL_CONTEXT (fieldlo) = struct_type;
00317 DECL_CONTEXT (fieldhi) = struct_type;
00318 TREE_CHAIN (fieldlo) = fieldhi;
00319 TYPE_FIELDS (struct_type) = fieldlo;
00320 TYPE_NAME (struct_type) = get_identifier ("__mf_cache");
00321 layout_type (struct_type);
00322
00323 return struct_type;
00324 }
00325
00326 #define build_function_type_0(rtype) \
00327 build_function_type (rtype, void_list_node)
00328 #define build_function_type_1(rtype, arg1) \
00329 build_function_type (rtype, tree_cons (0, arg1, void_list_node))
00330 #define build_function_type_3(rtype, arg1, arg2, arg3) \
00331 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
00332 tree_cons (0, arg3, void_list_node))))
00333 #define build_function_type_4(rtype, arg1, arg2, arg3, arg4) \
00334 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
00335 tree_cons (0, arg3, tree_cons (0, arg4, \
00336 void_list_node)))))
00337
00338
00339
00340 void
00341 mudflap_init (void)
00342 {
00343 static bool done = false;
00344 tree mf_const_string_type;
00345 tree mf_cache_array_type;
00346 tree mf_check_register_fntype;
00347 tree mf_unregister_fntype;
00348 tree mf_init_fntype;
00349 tree mf_set_options_fntype;
00350
00351 if (done)
00352 return;
00353 done = true;
00354
00355 mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode,
00356 true);
00357 mf_const_string_type
00358 = build_pointer_type (build_qualified_type
00359 (char_type_node, TYPE_QUAL_CONST));
00360
00361 mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type);
00362 mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
00363 mf_cache_array_type = build_array_type (mf_cache_struct_type, 0);
00364 mf_check_register_fntype =
00365 build_function_type_4 (void_type_node, ptr_type_node, size_type_node,
00366 integer_type_node, mf_const_string_type);
00367 mf_unregister_fntype =
00368 build_function_type_3 (void_type_node, ptr_type_node, size_type_node,
00369 integer_type_node);
00370 mf_init_fntype =
00371 build_function_type_0 (void_type_node);
00372 mf_set_options_fntype =
00373 build_function_type_1 (integer_type_node, mf_const_string_type);
00374
00375 mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
00376 mf_cache_array_type);
00377 mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift",
00378 unsigned_char_type_node);
00379 mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask",
00380 mf_uintptr_type);
00381
00382
00383 mf_mark (mf_cache_array_decl);
00384 mf_mark (mf_cache_shift_decl);
00385 mf_mark (mf_cache_mask_decl);
00386 mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check",
00387 mf_check_register_fntype);
00388 mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register",
00389 mf_check_register_fntype);
00390 mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister",
00391 mf_unregister_fntype);
00392 mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init",
00393 mf_init_fntype);
00394 mf_set_options_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_set_options",
00395 mf_set_options_fntype);
00396 }
00397 #undef build_function_type_4
00398 #undef build_function_type_3
00399 #undef build_function_type_1
00400 #undef build_function_type_0
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 static void
00413 execute_mudflap_function_ops (void)
00414 {
00415
00416
00417 if (mf_marked_p (current_function_decl) ||
00418 DECL_ARTIFICIAL (current_function_decl))
00419 return;
00420
00421 push_gimplify_context ();
00422
00423
00424 if (! flag_mudflap_threads)
00425 mf_decl_cache_locals ();
00426
00427 mf_xform_derefs ();
00428
00429 if (! flag_mudflap_threads)
00430 mf_decl_clear_locals ();
00431
00432 pop_gimplify_context (NULL);
00433 }
00434
00435
00436
00437
00438
00439 static void
00440 mf_decl_cache_locals (void)
00441 {
00442 tree t, shift_init_stmts, mask_init_stmts;
00443 tree_stmt_iterator tsi;
00444
00445
00446 mf_cache_shift_decl_l
00447 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl),
00448 "__mf_lookup_shift_l"));
00449
00450 mf_cache_mask_decl_l
00451 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl),
00452 "__mf_lookup_mask_l"));
00453
00454
00455
00456 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_shift_decl_l),
00457 mf_cache_shift_decl_l, mf_cache_shift_decl);
00458 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
00459 gimplify_to_stmt_list (&t);
00460 shift_init_stmts = t;
00461
00462 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_mask_decl_l),
00463 mf_cache_mask_decl_l, mf_cache_mask_decl);
00464 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
00465 gimplify_to_stmt_list (&t);
00466 mask_init_stmts = t;
00467
00468
00469
00470 for (tsi = tsi_start (shift_init_stmts);
00471 ! tsi_end_p (tsi);
00472 tsi_next (&tsi))
00473 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
00474
00475 for (tsi = tsi_start (mask_init_stmts);
00476 ! tsi_end_p (tsi);
00477 tsi_next (&tsi))
00478 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
00479 bsi_commit_edge_inserts ();
00480 }
00481
00482
00483 static void
00484 mf_decl_clear_locals (void)
00485 {
00486
00487 mf_cache_shift_decl_l = NULL_TREE;
00488 mf_cache_mask_decl_l = NULL_TREE;
00489 }
00490
00491 static void
00492 mf_build_check_statement_for (tree base, tree limit,
00493 block_stmt_iterator *instr_bsi,
00494 location_t *locus, tree dirflag)
00495 {
00496 tree_stmt_iterator head, tsi;
00497 block_stmt_iterator bsi;
00498 basic_block cond_bb, then_bb, join_bb;
00499 edge e;
00500 tree cond, t, u, v, l1, l2;
00501 tree mf_base;
00502 tree mf_elem;
00503 tree mf_limit;
00504
00505
00506
00507
00508
00509
00510
00511 l1 = create_artificial_label ();
00512 l2 = create_artificial_label ();
00513 cond_bb = bb_for_stmt (bsi_stmt (*instr_bsi));
00514 bsi = *instr_bsi;
00515 bsi_prev (&bsi);
00516 if (! bsi_end_p (bsi))
00517 {
00518
00519
00520
00521 e = split_block (cond_bb, bsi_stmt (bsi));
00522 cond_bb = e->src;
00523 join_bb = e->dest;
00524 }
00525 else
00526 {
00527
00528
00529
00530 join_bb = cond_bb;
00531 cond_bb = split_edge (find_edge (join_bb->prev_bb, join_bb));
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 then_bb = create_empty_bb (cond_bb);
00543 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
00544 make_single_succ_edge (then_bb, join_bb, EDGE_FALLTHRU);
00545
00546
00547
00548 predict_edge_def (EDGE_PRED (then_bb, 0), PRED_MUDFLAP, NOT_TAKEN);
00549
00550
00551 e = find_edge (cond_bb, join_bb);
00552 e->flags = EDGE_FALSE_VALUE;
00553 predict_edge_def (e, PRED_MUDFLAP, TAKEN);
00554
00555
00556
00557 if (dom_info_available_p (CDI_DOMINATORS))
00558 {
00559 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
00560 set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
00561 }
00562
00563
00564 mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
00565 mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
00566 mf_limit = create_tmp_var (mf_uintptr_type, "__mf_limit");
00567
00568
00569 t = build (MODIFY_EXPR, void_type_node, mf_base,
00570 convert (mf_uintptr_type, unshare_expr (base)));
00571 SET_EXPR_LOCUS (t, locus);
00572 gimplify_to_stmt_list (&t);
00573 head = tsi_start (t);
00574 tsi = tsi_last (t);
00575
00576
00577 t = build (MODIFY_EXPR, void_type_node, mf_limit,
00578 convert (mf_uintptr_type, unshare_expr (limit)));
00579 SET_EXPR_LOCUS (t, locus);
00580 gimplify_to_stmt_list (&t);
00581 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
00582
00583
00584
00585 t = build (RSHIFT_EXPR, mf_uintptr_type, mf_base,
00586 (flag_mudflap_threads ? mf_cache_shift_decl : mf_cache_shift_decl_l));
00587 t = build (BIT_AND_EXPR, mf_uintptr_type, t,
00588 (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l));
00589 t = build (ARRAY_REF,
00590 TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
00591 mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
00592 t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
00593 t = build (MODIFY_EXPR, void_type_node, mf_elem, t);
00594 SET_EXPR_LOCUS (t, locus);
00595 gimplify_to_stmt_list (&t);
00596 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 t = build (COMPONENT_REF, mf_uintptr_type,
00614 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
00615 TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
00616 t = build (GT_EXPR, boolean_type_node, t, mf_base);
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 u = build (COMPONENT_REF, mf_uintptr_type,
00627 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
00628 TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
00629
00630 v = mf_limit;
00631
00632 u = build (LT_EXPR, boolean_type_node, u, v);
00633
00634
00635
00636
00637 t = build (TRUTH_OR_EXPR, boolean_type_node, t, u);
00638 cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
00639 t = build (MODIFY_EXPR, boolean_type_node, cond, t);
00640 gimplify_to_stmt_list (&t);
00641 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
00642
00643
00644
00645 t = build (COND_EXPR, void_type_node, cond,
00646 build (GOTO_EXPR, void_type_node, tree_block_label (then_bb)),
00647 build (GOTO_EXPR, void_type_node, tree_block_label (join_bb)));
00648 SET_EXPR_LOCUS (t, locus);
00649 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662 bsi = bsi_last (cond_bb);
00663 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
00664 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
00665
00666
00667
00668
00669
00670
00671
00672
00673 u = tree_cons (NULL_TREE,
00674 mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION
00675 : *locus),
00676 NULL_TREE);
00677 u = tree_cons (NULL_TREE, dirflag, u);
00678
00679 u = tree_cons (NULL_TREE,
00680 fold (build (PLUS_EXPR, integer_type_node,
00681 fold (build (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base)),
00682 integer_one_node)),
00683 u);
00684 u = tree_cons (NULL_TREE, mf_base, u);
00685 t = build_function_call_expr (mf_check_fndecl, u);
00686 gimplify_to_stmt_list (&t);
00687 head = tsi_start (t);
00688 tsi = tsi_last (t);
00689
00690 if (! flag_mudflap_threads)
00691 {
00692 t = build (MODIFY_EXPR, void_type_node,
00693 mf_cache_shift_decl_l, mf_cache_shift_decl);
00694 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
00695
00696 t = build (MODIFY_EXPR, void_type_node,
00697 mf_cache_mask_decl_l, mf_cache_mask_decl);
00698 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
00699 }
00700
00701
00702 bsi = bsi_start (then_bb);
00703 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
00704 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
00705
00706 *instr_bsi = bsi_start (join_bb);
00707 bsi_next (instr_bsi);
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717 static int
00718 mf_decl_eligible_p (tree decl)
00719 {
00720 return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
00721
00722
00723
00724 && TREE_ADDRESSABLE (decl)
00725
00726 && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
00727
00728 && DECL_VALUE_EXPR (decl) == NULL);
00729 }
00730
00731
00732 static void
00733 mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
00734 location_t *locus, tree dirflag)
00735 {
00736 tree type, base, limit, addr, size, t;
00737
00738
00739 if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
00740 return;
00741
00742
00743 if (mf_marked_p (*tp))
00744 return;
00745
00746 t = *tp;
00747 type = TREE_TYPE (t);
00748 size = TYPE_SIZE_UNIT (type);
00749
00750 switch (TREE_CODE (t))
00751 {
00752 case ARRAY_REF:
00753 case COMPONENT_REF:
00754 {
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 tree var;
00765 int component_ref_only = (TREE_CODE (t) == COMPONENT_REF);
00766
00767
00768
00769 tree elt = NULL_TREE;
00770 int bitfield_ref_p = (TREE_CODE (t) == COMPONENT_REF
00771 && DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1)));
00772
00773
00774
00775 var = TREE_OPERAND (t, 0);
00776 while (1)
00777 {
00778 if (bitfield_ref_p && elt == NULL_TREE
00779 && (TREE_CODE (var) == ARRAY_REF || TREE_CODE (var) == COMPONENT_REF))
00780 elt = var;
00781
00782 if (TREE_CODE (var) == ARRAY_REF)
00783 {
00784 component_ref_only = 0;
00785 var = TREE_OPERAND (var, 0);
00786 }
00787 else if (TREE_CODE (var) == COMPONENT_REF)
00788 var = TREE_OPERAND (var, 0);
00789 else if (INDIRECT_REF_P (var))
00790 {
00791 base = TREE_OPERAND (var, 0);
00792 break;
00793 }
00794 else
00795 {
00796 gcc_assert (TREE_CODE (var) == VAR_DECL
00797 || TREE_CODE (var) == PARM_DECL
00798 || TREE_CODE (var) == RESULT_DECL
00799 || TREE_CODE (var) == STRING_CST);
00800
00801
00802
00803
00804 if (! mf_decl_eligible_p (var) || component_ref_only)
00805 return;
00806 else
00807 {
00808 base = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (var)), var);
00809 break;
00810 }
00811 }
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 if (bitfield_ref_p)
00824 {
00825 tree field = TREE_OPERAND (t, 1);
00826
00827 if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
00828 size = DECL_SIZE_UNIT (field);
00829
00830 if (elt)
00831 elt = build1 (ADDR_EXPR, build_pointer_type TREE_TYPE (elt), elt);
00832 addr = fold_convert (ptr_type_node, elt ? elt : base);
00833 addr = fold (build (PLUS_EXPR, ptr_type_node,
00834 addr, fold_convert (ptr_type_node,
00835 byte_position (field))));
00836 }
00837 else
00838 addr = build1 (ADDR_EXPR, build_pointer_type (type), t);
00839
00840 limit = fold (build (MINUS_EXPR, mf_uintptr_type,
00841 fold (build2 (PLUS_EXPR, mf_uintptr_type,
00842 convert (mf_uintptr_type, addr),
00843 size)),
00844 integer_one_node));
00845 }
00846 break;
00847
00848 case INDIRECT_REF:
00849 addr = TREE_OPERAND (t, 0);
00850 base = addr;
00851 limit = fold (build (MINUS_EXPR, ptr_type_node,
00852 fold (build (PLUS_EXPR, ptr_type_node, base, size)),
00853 integer_one_node));
00854 break;
00855
00856 case ARRAY_RANGE_REF:
00857 warning ("mudflap checking not yet implemented for ARRAY_RANGE_REF");
00858 return;
00859
00860 case BIT_FIELD_REF:
00861
00862 {
00863 tree ofs, rem, bpu;
00864
00865
00866
00867 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
00868 return;
00869
00870 bpu = bitsize_int (BITS_PER_UNIT);
00871 ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
00872 rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
00873 ofs = size_binop (TRUNC_DIV_EXPR, ofs, bpu);
00874
00875 size = convert (bitsizetype, TREE_OPERAND (t, 1));
00876 size = size_binop (PLUS_EXPR, size, rem);
00877 size = size_binop (CEIL_DIV_EXPR, size, bpu);
00878 size = convert (sizetype, size);
00879
00880 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
00881 addr = convert (ptr_type_node, addr);
00882 addr = fold (build (PLUS_EXPR, ptr_type_node, addr, ofs));
00883
00884 base = addr;
00885 limit = fold (build (MINUS_EXPR, ptr_type_node,
00886 fold (build (PLUS_EXPR, ptr_type_node, base, size)),
00887 integer_one_node));
00888 }
00889 break;
00890
00891 default:
00892 return;
00893 }
00894
00895 mf_build_check_statement_for (base, limit, iter, locus, dirflag);
00896 }
00897
00898 static void
00899 mf_xform_derefs (void)
00900 {
00901 basic_block bb, next;
00902 block_stmt_iterator i;
00903 int saved_last_basic_block = last_basic_block;
00904
00905 bb = ENTRY_BLOCK_PTR ->next_bb;
00906 do
00907 {
00908 next = bb->next_bb;
00909 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
00910 {
00911 tree s = bsi_stmt (i);
00912
00913
00914 switch (TREE_CODE (s))
00915 {
00916 case MODIFY_EXPR:
00917 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
00918 integer_one_node);
00919 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 1), EXPR_LOCUS (s),
00920 integer_zero_node);
00921 break;
00922
00923 case RETURN_EXPR:
00924 if (TREE_OPERAND (s, 0) != NULL_TREE)
00925 {
00926 if (TREE_CODE (TREE_OPERAND (s, 0)) == MODIFY_EXPR)
00927 mf_xform_derefs_1 (&i, &TREE_OPERAND (TREE_OPERAND (s, 0), 1),
00928 EXPR_LOCUS (s), integer_zero_node);
00929 else
00930 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
00931 integer_zero_node);
00932 }
00933 break;
00934
00935 default:
00936 ;
00937 }
00938 }
00939 bb = next;
00940 }
00941 while (bb && bb->index <= saved_last_basic_block);
00942 }
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953 static void
00954 execute_mudflap_function_decls (void)
00955 {
00956
00957
00958 if (mf_marked_p (current_function_decl) ||
00959 DECL_ARTIFICIAL (current_function_decl))
00960 return;
00961
00962 push_gimplify_context ();
00963
00964 mf_xform_decls (DECL_SAVED_TREE (current_function_decl),
00965 DECL_ARGUMENTS (current_function_decl));
00966
00967 pop_gimplify_context (NULL);
00968 }
00969
00970
00971
00972
00973 struct mf_xform_decls_data
00974 {
00975 tree param_decls;
00976 };
00977
00978
00979
00980
00981
00982 static void
00983 mx_register_decls (tree decl, tree *stmt_list)
00984 {
00985 tree finally_stmts = NULL_TREE;
00986 tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);
00987
00988 while (decl != NULL_TREE)
00989 {
00990 if (mf_decl_eligible_p (decl)
00991
00992 && ! mf_marked_p (decl)
00993
00994 && ! DECL_EXTERNAL (decl)
00995 && ! TREE_STATIC (decl))
00996 {
00997 tree size = NULL_TREE, variable_name;
00998 tree unregister_fncall, unregister_fncall_params;
00999 tree register_fncall, register_fncall_params;
01000
01001 size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
01002
01003
01004 unregister_fncall_params =
01005 tree_cons (NULL_TREE,
01006 convert (ptr_type_node,
01007 mf_mark (build1 (ADDR_EXPR,
01008 build_pointer_type (TREE_TYPE (decl)),
01009 decl))),
01010 tree_cons (NULL_TREE,
01011 size,
01012 tree_cons (NULL_TREE,
01013
01014 build_int_cst (NULL_TREE, 3),
01015 NULL_TREE)));
01016
01017 unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
01018 unregister_fncall_params);
01019
01020
01021 variable_name = mf_varname_tree (decl);
01022 register_fncall_params =
01023 tree_cons (NULL_TREE,
01024 convert (ptr_type_node,
01025 mf_mark (build1 (ADDR_EXPR,
01026 build_pointer_type (TREE_TYPE (decl)),
01027 decl))),
01028 tree_cons (NULL_TREE,
01029 size,
01030 tree_cons (NULL_TREE,
01031
01032 build_int_cst (NULL_TREE, 3),
01033 tree_cons (NULL_TREE,
01034 variable_name,
01035 NULL_TREE))));
01036
01037
01038 register_fncall = build_function_call_expr (mf_register_fndecl,
01039 register_fncall_params);
01040
01041
01042
01043 gimplify_stmt (®ister_fncall);
01044 gimplify_stmt (&unregister_fncall);
01045
01046
01047 if (tsi_end_p (initially_stmts))
01048 warning ("mudflap cannot track %qs in stub function",
01049 IDENTIFIER_POINTER (DECL_NAME (decl)));
01050 else
01051 {
01052 tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);
01053
01054
01055 append_to_statement_list (unregister_fncall, &finally_stmts);
01056 }
01057 mf_mark (decl);
01058 }
01059
01060 decl = TREE_CHAIN (decl);
01061 }
01062
01063
01064 if (finally_stmts != NULL_TREE)
01065 {
01066 tree t = build (TRY_FINALLY_EXPR, void_type_node,
01067 *stmt_list, finally_stmts);
01068 *stmt_list = NULL;
01069 append_to_statement_list (t, stmt_list);
01070 }
01071 }
01072
01073
01074
01075 static tree
01076 mx_xfn_xform_decls (tree *t, int *continue_p, void *data)
01077 {
01078 struct mf_xform_decls_data* d = (struct mf_xform_decls_data*) data;
01079
01080 if (*t == NULL_TREE || *t == error_mark_node)
01081 {
01082 *continue_p = 0;
01083 return NULL_TREE;
01084 }
01085
01086 *continue_p = 1;
01087
01088 switch (TREE_CODE (*t))
01089 {
01090 case BIND_EXPR:
01091 {
01092
01093 mx_register_decls (d->param_decls, &BIND_EXPR_BODY (*t));
01094 d->param_decls = NULL_TREE;
01095
01096 mx_register_decls (BIND_EXPR_VARS (*t), &BIND_EXPR_BODY (*t));
01097 }
01098 break;
01099
01100 default:
01101 break;
01102 }
01103
01104 return NULL_TREE;
01105 }
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115 static void
01116 mf_xform_decls (tree fnbody, tree fnparams)
01117 {
01118 struct mf_xform_decls_data d;
01119 d.param_decls = fnparams;
01120 walk_tree_without_duplicates (&fnbody, mx_xfn_xform_decls, &d);
01121 }
01122
01123
01124
01125
01126
01127
01128
01129
01130 static GTY ((param_is (union tree_node))) htab_t marked_trees = NULL;
01131
01132 tree
01133 mf_mark (tree t)
01134 {
01135 void **slot;
01136
01137 if (marked_trees == NULL)
01138 marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer, NULL);
01139
01140 slot = htab_find_slot (marked_trees, t, INSERT);
01141 *slot = t;
01142 return t;
01143 }
01144
01145 int
01146 mf_marked_p (tree t)
01147 {
01148 void *entry;
01149
01150 if (marked_trees == NULL)
01151 return 0;
01152
01153 entry = htab_find (marked_trees, t);
01154 return (entry != NULL);
01155 }
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166 static GTY (()) varray_type deferred_static_decls;
01167
01168
01169 static GTY (()) tree enqueued_call_stmt_chain;
01170
01171 static void
01172 mudflap_register_call (tree obj, tree object_size, tree varname)
01173 {
01174 tree arg, args, call_stmt;
01175
01176 args = tree_cons (NULL_TREE, varname, NULL_TREE);
01177
01178 arg = build_int_cst (NULL_TREE, 4);
01179 args = tree_cons (NULL_TREE, arg, args);
01180
01181 arg = convert (size_type_node, object_size);
01182 args = tree_cons (NULL_TREE, arg, args);
01183
01184 arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
01185 arg = convert (ptr_type_node, arg);
01186 args = tree_cons (NULL_TREE, arg, args);
01187
01188 call_stmt = build_function_call_expr (mf_register_fndecl, args);
01189
01190 append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
01191 }
01192
01193 void
01194 mudflap_enqueue_decl (tree obj)
01195 {
01196 if (mf_marked_p (obj))
01197 return;
01198
01199
01200
01201
01202
01203
01204 if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj))
01205 return;
01206
01207 if (! deferred_static_decls)
01208 VARRAY_TREE_INIT (deferred_static_decls, 10, "deferred static list");
01209
01210 VARRAY_PUSH_TREE (deferred_static_decls, obj);
01211 }
01212
01213
01214 void
01215 mudflap_enqueue_constant (tree obj)
01216 {
01217 tree object_size, varname;
01218
01219 if (mf_marked_p (obj))
01220 return;
01221
01222 if (TREE_CODE (obj) == STRING_CST)
01223 object_size = build_int_cst (NULL_TREE, TREE_STRING_LENGTH (obj));
01224 else
01225 object_size = size_in_bytes (TREE_TYPE (obj));
01226
01227 if (TREE_CODE (obj) == STRING_CST)
01228 varname = mf_build_string ("string literal");
01229 else
01230 varname = mf_build_string ("constant");
01231
01232 mudflap_register_call (obj, object_size, varname);
01233 }
01234
01235
01236
01237 void
01238 mudflap_finish_file (void)
01239 {
01240 tree ctor_statements = NULL_TREE;
01241
01242
01243 {
01244 tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
01245 append_to_statement_list (call2_stmt, &ctor_statements);
01246 }
01247
01248
01249 if (flag_mudflap_ignore_reads)
01250 {
01251 tree arg = tree_cons (NULL_TREE,
01252 mf_build_string ("-ignore-reads"), NULL_TREE);
01253 tree call_stmt = build_function_call_expr (mf_set_options_fndecl, arg);
01254 append_to_statement_list (call_stmt, &ctor_statements);
01255 }
01256
01257
01258 if (deferred_static_decls)
01259 {
01260 size_t i;
01261 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
01262 {
01263 tree obj = VARRAY_TREE (deferred_static_decls, i);
01264
01265 gcc_assert (DECL_P (obj));
01266
01267 if (mf_marked_p (obj))
01268 continue;
01269
01270
01271
01272
01273
01274 if (TREE_STATIC (obj) && ! TREE_ADDRESSABLE (obj))
01275 continue;
01276
01277 if (! COMPLETE_TYPE_P (TREE_TYPE (obj)))
01278 {
01279 warning ("mudflap cannot track unknown size extern %qs",
01280 IDENTIFIER_POINTER (DECL_NAME (obj)));
01281 continue;
01282 }
01283
01284 mudflap_register_call (obj,
01285 size_in_bytes (TREE_TYPE (obj)),
01286 mf_varname_tree (obj));
01287 }
01288
01289 VARRAY_CLEAR (deferred_static_decls);
01290 }
01291
01292
01293 if (enqueued_call_stmt_chain)
01294 {
01295 append_to_statement_list (enqueued_call_stmt_chain, &ctor_statements);
01296 enqueued_call_stmt_chain = NULL_TREE;
01297 }
01298
01299 cgraph_build_static_cdtor ('I', ctor_statements,
01300 MAX_RESERVED_INIT_PRIORITY-1);
01301 }
01302
01303
01304 static bool
01305 gate_mudflap (void)
01306 {
01307 return flag_mudflap != 0;
01308 }
01309
01310 struct tree_opt_pass pass_mudflap_1 =
01311 {
01312 "mudflap1",
01313 gate_mudflap,
01314 execute_mudflap_function_decls,
01315 NULL,
01316 NULL,
01317 0,
01318 0,
01319 PROP_gimple_any,
01320 0,
01321 0,
01322 0,
01323 TODO_dump_func,
01324 0
01325 };
01326
01327 struct tree_opt_pass pass_mudflap_2 =
01328 {
01329 "mudflap2",
01330 gate_mudflap,
01331 execute_mudflap_function_ops,
01332 NULL,
01333 NULL,
01334 0,
01335 0,
01336 PROP_gimple_leh,
01337 0,
01338 0,
01339 0,
01340 TODO_verify_flow | TODO_verify_stmts
01341 | TODO_dump_func,
01342 0
01343 };
01344
01345 #include "gt-tree-mudflap.h"