OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [tree-mudflap.c] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
2
   Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
3
   Contributed by Frank Ch. Eigler <fche@redhat.com>
4
   and Graydon Hoare <graydon@redhat.com>
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify it under
9
the terms of the GNU General Public License as published by the Free
10
Software Foundation; either version 3, or (at your option) any later
11
version.
12
 
13
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14
WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with GCC; see the file COPYING3.  If not see
20
<http://www.gnu.org/licenses/>.  */
21
 
22
 
23
#include "config.h"
24
#include "system.h"
25
#include "coretypes.h"
26
#include "tm.h"
27
#include "hard-reg-set.h"
28
#include "rtl.h"
29
#include "tree.h"
30
#include "tm_p.h"
31
#include "basic-block.h"
32
#include "flags.h"
33
#include "function.h"
34
#include "tree-inline.h"
35
#include "tree-gimple.h"
36
#include "tree-flow.h"
37
#include "tree-mudflap.h"
38
#include "tree-dump.h"
39
#include "tree-pass.h"
40
#include "hashtab.h"
41
#include "diagnostic.h"
42
#include <demangle.h>
43
#include "langhooks.h"
44
#include "ggc.h"
45
#include "cgraph.h"
46
#include "toplev.h"
47
 
48
/* Internal function decls */
49
 
50
 
51
/* Options.  */
52
#define flag_mudflap_threads (flag_mudflap == 2)
53
 
54
/* Helpers.  */
55
static tree mf_build_string (const char *string);
56
static tree mf_varname_tree (tree);
57
static tree mf_file_function_line_tree (location_t);
58
 
59
/* Indirection-related instrumentation.  */
60
static void mf_decl_cache_locals (void);
61
static void mf_decl_clear_locals (void);
62
static void mf_xform_derefs (void);
63
static unsigned int execute_mudflap_function_ops (void);
64
 
65
/* Addressable variables instrumentation.  */
66
static void mf_xform_decls (tree, tree);
67
static tree mx_xfn_xform_decls (tree *, int *, void *);
68
static void mx_register_decls (tree, tree *);
69
static unsigned int execute_mudflap_function_decls (void);
70
 
71
 
72
/* ------------------------------------------------------------------------ */
73
/* Some generally helpful functions for mudflap instrumentation.  */
74
 
75
/* Build a reference to a literal string.  */
76
static tree
77
mf_build_string (const char *string)
78
{
79
  size_t len = strlen (string);
80
  tree result = mf_mark (build_string (len + 1, string));
81
 
82
  TREE_TYPE (result) = build_array_type
83
    (char_type_node, build_index_type (build_int_cst (NULL_TREE, len)));
84
  TREE_CONSTANT (result) = 1;
85
  TREE_INVARIANT (result) = 1;
86
  TREE_READONLY (result) = 1;
87
  TREE_STATIC (result) = 1;
88
 
89
  result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result);
90
 
91
  return mf_mark (result);
92
}
93
 
94
/* Create a properly typed STRING_CST node that describes the given
95
   declaration.  It will be used as an argument for __mf_register().
96
   Try to construct a helpful string, including file/function/variable
97
   name.  */
98
 
99
static tree
100
mf_varname_tree (tree decl)
101
{
102
  static pretty_printer buf_rec;
103
  static int initialized = 0;
104
  pretty_printer *buf = & buf_rec;
105
  const char *buf_contents;
106
  tree result;
107
 
108
  gcc_assert (decl);
109
 
110
  if (!initialized)
111
    {
112
      pp_construct (buf, /* prefix */ NULL, /* line-width */ 0);
113
      initialized = 1;
114
    }
115
  pp_clear_output_area (buf);
116
 
117
  /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]].  */
118
  {
119
    expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (decl));
120
    const char *sourcefile;
121
    unsigned sourceline = xloc.line;
122
    unsigned sourcecolumn = 0;
123
#ifdef USE_MAPPED_LOCATION
124
    sourcecolumn = xloc.column;
125
#endif
126
    sourcefile = xloc.file;
127
    if (sourcefile == NULL && current_function_decl != NULL_TREE)
128
      sourcefile = DECL_SOURCE_FILE (current_function_decl);
129
    if (sourcefile == NULL)
130
      sourcefile = "<unknown file>";
131
 
132
    pp_string (buf, sourcefile);
133
 
134
    if (sourceline != 0)
135
      {
136
        pp_string (buf, ":");
137
        pp_decimal_int (buf, sourceline);
138
 
139
        if (sourcecolumn != 0)
140
          {
141
            pp_string (buf, ":");
142
            pp_decimal_int (buf, sourcecolumn);
143
          }
144
      }
145
  }
146
 
147
  if (current_function_decl != NULL_TREE)
148
    {
149
      /* Add (FUNCTION) */
150
      pp_string (buf, " (");
151
      {
152
        const char *funcname = NULL;
153
        if (DECL_NAME (current_function_decl))
154
          funcname = lang_hooks.decl_printable_name (current_function_decl, 1);
155
        if (funcname == NULL)
156
          funcname = "anonymous fn";
157
 
158
        pp_string (buf, funcname);
159
      }
160
      pp_string (buf, ") ");
161
    }
162
  else
163
    pp_string (buf, " ");
164
 
165
  /* Add <variable-declaration>, possibly demangled.  */
166
  {
167
    const char *declname = NULL;
168
 
169
    if (DECL_NAME (decl) != NULL)
170
      {
171
        if (strcmp ("GNU C++", lang_hooks.name) == 0)
172
          {
173
            /* The gcc/cp decl_printable_name hook doesn't do as good a job as
174
               the libiberty demangler.  */
175
            declname = cplus_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)),
176
                                       DMGL_AUTO | DMGL_VERBOSE);
177
          }
178
        if (declname == NULL)
179
          declname = lang_hooks.decl_printable_name (decl, 3);
180
      }
181
    if (declname == NULL)
182
      declname = "<unnamed variable>";
183
 
184
    pp_string (buf, declname);
185
  }
186
 
187
  /* Return the lot as a new STRING_CST.  */
188
  buf_contents = pp_base_formatted_text (buf);
189
  result = mf_build_string (buf_contents);
190
  pp_clear_output_area (buf);
191
 
192
  return result;
193
}
194
 
195
 
196
/* And another friend, for producing a simpler message.  */
197
 
198
static tree
199
mf_file_function_line_tree (location_t location)
200
{
201
  expanded_location xloc = expand_location (location);
202
  const char *file = NULL, *colon, *line, *op, *name, *cp;
203
  char linecolbuf[30]; /* Enough for two decimal numbers plus a colon.  */
204
  char *string;
205
  tree result;
206
 
207
  /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]].  */
208
  file = xloc.file;
209
  if (file == NULL && current_function_decl != NULL_TREE)
210
    file = DECL_SOURCE_FILE (current_function_decl);
211
  if (file == NULL)
212
    file = "<unknown file>";
213
 
214
  if (xloc.line > 0)
215
    {
216
#ifdef USE_MAPPED_LOCATION
217
      if (xloc.column > 0)
218
        sprintf (linecolbuf, "%d:%d", xloc.line, xloc.column);
219
      else
220
#endif
221
        sprintf (linecolbuf, "%d", xloc.line);
222
      colon = ":";
223
      line = linecolbuf;
224
    }
225
  else
226
    colon = line = "";
227
 
228
  /* Add (FUNCTION).  */
229
  name = lang_hooks.decl_printable_name (current_function_decl, 1);
230
  if (name)
231
    {
232
      op = " (";
233
      cp = ")";
234
    }
235
  else
236
    op = name = cp = "";
237
 
238
  string = concat (file, colon, line, op, name, cp, NULL);
239
  result = mf_build_string (string);
240
  free (string);
241
 
242
  return result;
243
}
244
 
245
 
246
/* global tree nodes */
247
 
248
/* Global tree objects for global variables and functions exported by
249
   mudflap runtime library.  mf_init_extern_trees must be called
250
   before using these.  */
251
 
252
/* uintptr_t (usually "unsigned long") */
253
static GTY (()) tree mf_uintptr_type;
254
 
255
/* struct __mf_cache { uintptr_t low; uintptr_t high; }; */
256
static GTY (()) tree mf_cache_struct_type;
257
 
258
/* struct __mf_cache * const */
259
static GTY (()) tree mf_cache_structptr_type;
260
 
261
/* extern struct __mf_cache __mf_lookup_cache []; */
262
static GTY (()) tree mf_cache_array_decl;
263
 
264
/* extern unsigned char __mf_lc_shift; */
265
static GTY (()) tree mf_cache_shift_decl;
266
 
267
/* extern uintptr_t __mf_lc_mask; */
268
static GTY (()) tree mf_cache_mask_decl;
269
 
270
/* Their function-scope local shadows, used in single-threaded mode only.  */
271
 
272
/* auto const unsigned char __mf_lc_shift_l; */
273
static GTY (()) tree mf_cache_shift_decl_l;
274
 
275
/* auto const uintptr_t __mf_lc_mask_l; */
276
static GTY (()) tree mf_cache_mask_decl_l;
277
 
278
/* extern void __mf_check (void *ptr, size_t sz, int type, const char *); */
279
static GTY (()) tree mf_check_fndecl;
280
 
281
/* extern void __mf_register (void *ptr, size_t sz, int type, const char *); */
282
static GTY (()) tree mf_register_fndecl;
283
 
284
/* extern void __mf_unregister (void *ptr, size_t sz, int type); */
285
static GTY (()) tree mf_unregister_fndecl;
286
 
287
/* extern void __mf_init (); */
288
static GTY (()) tree mf_init_fndecl;
289
 
290
/* extern int __mf_set_options (const char*); */
291
static GTY (()) tree mf_set_options_fndecl;
292
 
293
 
294
/* Helper for mudflap_init: construct a decl with the given category,
295
   name, and type, mark it an external reference, and pushdecl it.  */
296
static inline tree
297
mf_make_builtin (enum tree_code category, const char *name, tree type)
298
{
299
  tree decl = mf_mark (build_decl (category, get_identifier (name), type));
300
  TREE_PUBLIC (decl) = 1;
301
  DECL_EXTERNAL (decl) = 1;
302
  lang_hooks.decls.pushdecl (decl);
303
  return decl;
304
}
305
 
306
/* Helper for mudflap_init: construct a tree corresponding to the type
307
     struct __mf_cache { uintptr_t low; uintptr_t high; };
308
     where uintptr_t is the FIELD_TYPE argument.  */
309
static inline tree
310
mf_make_mf_cache_struct_type (tree field_type)
311
{
312
  /* There is, abominably, no language-independent way to construct a
313
     RECORD_TYPE.  So we have to call the basic type construction
314
     primitives by hand.  */
315
  tree fieldlo = build_decl (FIELD_DECL, get_identifier ("low"), field_type);
316
  tree fieldhi = build_decl (FIELD_DECL, get_identifier ("high"), field_type);
317
 
318
  tree struct_type = make_node (RECORD_TYPE);
319
  DECL_CONTEXT (fieldlo) = struct_type;
320
  DECL_CONTEXT (fieldhi) = struct_type;
321
  TREE_CHAIN (fieldlo) = fieldhi;
322
  TYPE_FIELDS (struct_type) = fieldlo;
323
  TYPE_NAME (struct_type) = get_identifier ("__mf_cache");
324
  layout_type (struct_type);
325
 
326
  return struct_type;
327
}
328
 
329
#define build_function_type_0(rtype)            \
330
  build_function_type (rtype, void_list_node)
331
#define build_function_type_1(rtype, arg1)                 \
332
  build_function_type (rtype, tree_cons (0, arg1, void_list_node))
333
#define build_function_type_3(rtype, arg1, arg2, arg3)                  \
334
  build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2,   \
335
                                                             tree_cons (0, arg3, void_list_node))))
336
#define build_function_type_4(rtype, arg1, arg2, arg3, arg4)            \
337
  build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2,   \
338
                                                             tree_cons (0, arg3, tree_cons (0, arg4, \
339
                                                                                            void_list_node)))))
340
 
341
/* Initialize the global tree nodes that correspond to mf-runtime.h
342
   declarations.  */
343
void
344
mudflap_init (void)
345
{
346
  static bool done = false;
347
  tree mf_const_string_type;
348
  tree mf_cache_array_type;
349
  tree mf_check_register_fntype;
350
  tree mf_unregister_fntype;
351
  tree mf_init_fntype;
352
  tree mf_set_options_fntype;
353
 
354
  if (done)
355
    return;
356
  done = true;
357
 
358
  mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode,
359
                                                    /*unsignedp=*/true);
360
  mf_const_string_type
361
    = build_pointer_type (build_qualified_type
362
                          (char_type_node, TYPE_QUAL_CONST));
363
 
364
  mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type);
365
  mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
366
  mf_cache_array_type = build_array_type (mf_cache_struct_type, 0);
367
  mf_check_register_fntype =
368
    build_function_type_4 (void_type_node, ptr_type_node, size_type_node,
369
                           integer_type_node, mf_const_string_type);
370
  mf_unregister_fntype =
371
    build_function_type_3 (void_type_node, ptr_type_node, size_type_node,
372
                           integer_type_node);
373
  mf_init_fntype =
374
    build_function_type_0 (void_type_node);
375
  mf_set_options_fntype =
376
    build_function_type_1 (integer_type_node, mf_const_string_type);
377
 
378
  mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
379
                                         mf_cache_array_type);
380
  mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift",
381
                                         unsigned_char_type_node);
382
  mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask",
383
                                        mf_uintptr_type);
384
  /* Don't process these in mudflap_enqueue_decl, should they come by
385
     there for some reason.  */
386
  mf_mark (mf_cache_array_decl);
387
  mf_mark (mf_cache_shift_decl);
388
  mf_mark (mf_cache_mask_decl);
389
  mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check",
390
                                     mf_check_register_fntype);
391
  mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register",
392
                                        mf_check_register_fntype);
393
  mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister",
394
                                          mf_unregister_fntype);
395
  mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init",
396
                                    mf_init_fntype);
397
  mf_set_options_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_set_options",
398
                                           mf_set_options_fntype);
399
}
400
#undef build_function_type_4
401
#undef build_function_type_3
402
#undef build_function_type_1
403
#undef build_function_type_0
404
 
405
 
406
/* ------------------------------------------------------------------------ */
407
/* Memory reference transforms. Perform the mudflap indirection-related
408
   tree transforms on the current function.
409
 
410
   This is the second part of the mudflap instrumentation.  It works on
411
   low-level GIMPLE using the CFG, because we want to run this pass after
412
   tree optimizations have been performed, but we have to preserve the CFG
413
   for expansion from trees to RTL.  */
414
 
415
static unsigned int
416
execute_mudflap_function_ops (void)
417
{
418
  /* Don't instrument functions such as the synthetic constructor
419
     built during mudflap_finish_file.  */
420
  if (mf_marked_p (current_function_decl) ||
421
      DECL_ARTIFICIAL (current_function_decl))
422
    return 0;
423
 
424
  push_gimplify_context ();
425
 
426
  /* In multithreaded mode, don't cache the lookup cache parameters.  */
427
  if (! flag_mudflap_threads)
428
    mf_decl_cache_locals ();
429
 
430
  mf_xform_derefs ();
431
 
432
  if (! flag_mudflap_threads)
433
    mf_decl_clear_locals ();
434
 
435
  pop_gimplify_context (NULL);
436
  return 0;
437
}
438
 
439
/* Create and initialize local shadow variables for the lookup cache
440
   globals.  Put their decls in the *_l globals for use by
441
   mf_build_check_statement_for.  */
442
 
443
static void
444
mf_decl_cache_locals (void)
445
{
446
  tree t, shift_init_stmts, mask_init_stmts;
447
  tree_stmt_iterator tsi;
448
 
449
  /* Build the cache vars.  */
450
  mf_cache_shift_decl_l
451
    = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl),
452
                               "__mf_lookup_shift_l"));
453
 
454
  mf_cache_mask_decl_l
455
    = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl),
456
                               "__mf_lookup_mask_l"));
457
 
458
  /* Build initialization nodes for the cache vars.  We just load the
459
     globals into the cache variables.  */
460
  t = build2 (MODIFY_EXPR, TREE_TYPE (mf_cache_shift_decl_l),
461
              mf_cache_shift_decl_l, mf_cache_shift_decl);
462
  SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
463
  gimplify_to_stmt_list (&t);
464
  shift_init_stmts = t;
465
 
466
  t = build2 (MODIFY_EXPR, TREE_TYPE (mf_cache_mask_decl_l),
467
              mf_cache_mask_decl_l, mf_cache_mask_decl);
468
  SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
469
  gimplify_to_stmt_list (&t);
470
  mask_init_stmts = t;
471
 
472
  /* Anticipating multiple entry points, we insert the cache vars
473
     initializers in each successor of the ENTRY_BLOCK_PTR.  */
474
  for (tsi = tsi_start (shift_init_stmts);
475
       ! tsi_end_p (tsi);
476
       tsi_next (&tsi))
477
    insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
478
 
479
  for (tsi = tsi_start (mask_init_stmts);
480
       ! tsi_end_p (tsi);
481
       tsi_next (&tsi))
482
    insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
483
  bsi_commit_edge_inserts ();
484
}
485
 
486
 
487
static void
488
mf_decl_clear_locals (void)
489
{
490
  /* Unset local shadows.  */
491
  mf_cache_shift_decl_l = NULL_TREE;
492
  mf_cache_mask_decl_l = NULL_TREE;
493
}
494
 
495
static void
496
mf_build_check_statement_for (tree base, tree limit,
497
                              block_stmt_iterator *instr_bsi,
498
                              location_t *locus, tree dirflag)
499
{
500
  tree_stmt_iterator head, tsi;
501
  block_stmt_iterator bsi;
502
  basic_block cond_bb, then_bb, join_bb;
503
  edge e;
504
  tree cond, t, u, v;
505
  tree mf_base;
506
  tree mf_elem;
507
  tree mf_limit;
508
 
509
  /* We first need to split the current basic block, and start altering
510
     the CFG.  This allows us to insert the statements we're about to
511
     construct into the right basic blocks.  */
512
 
513
  cond_bb = bb_for_stmt (bsi_stmt (*instr_bsi));
514
  bsi = *instr_bsi;
515
  bsi_prev (&bsi);
516
  if (! bsi_end_p (bsi))
517
    e = split_block (cond_bb, bsi_stmt (bsi));
518
  else
519
    e = split_block_after_labels (cond_bb);
520
  cond_bb = e->src;
521
  join_bb = e->dest;
522
 
523
  /* A recap at this point: join_bb is the basic block at whose head
524
     is the gimple statement for which this check expression is being
525
     built.  cond_bb is the (possibly new, synthetic) basic block the
526
     end of which will contain the cache-lookup code, and a
527
     conditional that jumps to the cache-miss code or, much more
528
     likely, over to join_bb.  */
529
 
530
  /* Create the bb that contains the cache-miss fallback block (mf_check).  */
531
  then_bb = create_empty_bb (cond_bb);
532
  make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
533
  make_single_succ_edge (then_bb, join_bb, EDGE_FALLTHRU);
534
 
535
  /* Mark the pseudo-fallthrough edge from cond_bb to join_bb.  */
536
  e = find_edge (cond_bb, join_bb);
537
  e->flags = EDGE_FALSE_VALUE;
538
  e->count = cond_bb->count;
539
  e->probability = REG_BR_PROB_BASE;
540
 
541
  /* Update dominance info.  Note that bb_join's data was
542
     updated by split_block.  */
543
  if (dom_info_available_p (CDI_DOMINATORS))
544
    {
545
      set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
546
      set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
547
    }
548
 
549
  /* Build our local variables.  */
550
  mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
551
  mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
552
  mf_limit = create_tmp_var (mf_uintptr_type, "__mf_limit");
553
 
554
  /* Build: __mf_base = (uintptr_t) <base address expression>.  */
555
  t = build2 (MODIFY_EXPR, void_type_node, mf_base,
556
              convert (mf_uintptr_type, unshare_expr (base)));
557
  SET_EXPR_LOCUS (t, locus);
558
  gimplify_to_stmt_list (&t);
559
  head = tsi_start (t);
560
  tsi = tsi_last (t);
561
 
562
  /* Build: __mf_limit = (uintptr_t) <limit address expression>.  */
563
  t = build2 (MODIFY_EXPR, void_type_node, mf_limit,
564
              convert (mf_uintptr_type, unshare_expr (limit)));
565
  SET_EXPR_LOCUS (t, locus);
566
  gimplify_to_stmt_list (&t);
567
  tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
568
 
569
  /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
570
                                            & __mf_mask].  */
571
  t = build2 (RSHIFT_EXPR, mf_uintptr_type, mf_base,
572
              (flag_mudflap_threads ? mf_cache_shift_decl : mf_cache_shift_decl_l));
573
  t = build2 (BIT_AND_EXPR, mf_uintptr_type, t,
574
              (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l));
575
  t = build4 (ARRAY_REF,
576
              TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
577
              mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
578
  t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
579
  t = build2 (MODIFY_EXPR, void_type_node, mf_elem, t);
580
  SET_EXPR_LOCUS (t, locus);
581
  gimplify_to_stmt_list (&t);
582
  tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
583
 
584
  /* Quick validity check.
585
 
586
     if (__mf_elem->low > __mf_base
587
         || (__mf_elem_high < __mf_limit))
588
        {
589
          __mf_check ();
590
          ... and only if single-threaded:
591
          __mf_lookup_shift_1 = f...;
592
          __mf_lookup_mask_l = ...;
593
        }
594
 
595
     It is expected that this body of code is rarely executed so we mark
596
     the edge to the THEN clause of the conditional jump as unlikely.  */
597
 
598
  /* Construct t <-- '__mf_elem->low  > __mf_base'.  */
599
  t = build3 (COMPONENT_REF, mf_uintptr_type,
600
              build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
601
              TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
602
  t = build2 (GT_EXPR, boolean_type_node, t, mf_base);
603
 
604
  /* Construct '__mf_elem->high < __mf_limit'.
605
 
606
     First build:
607
        1) u <--  '__mf_elem->high'
608
        2) v <--  '__mf_limit'.
609
 
610
     Then build 'u <-- (u < v).  */
611
 
612
  u = build3 (COMPONENT_REF, mf_uintptr_type,
613
              build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
614
              TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
615
 
616
  v = mf_limit;
617
 
618
  u = build2 (LT_EXPR, boolean_type_node, u, v);
619
 
620
  /* Build the composed conditional: t <-- 't || u'.  Then store the
621
     result of the evaluation of 't' in a temporary variable which we
622
     can use as the condition for the conditional jump.  */
623
  t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u);
624
  cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
625
  t = build2 (MODIFY_EXPR, boolean_type_node, cond, t);
626
  gimplify_to_stmt_list (&t);
627
  tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
628
 
629
  /* Build the conditional jump.  'cond' is just a temporary so we can
630
     simply build a void COND_EXPR.  We do need labels in both arms though.  */
631
  t = build3 (COND_EXPR, void_type_node, cond,
632
              build1 (GOTO_EXPR, void_type_node, tree_block_label (then_bb)),
633
              build1 (GOTO_EXPR, void_type_node, tree_block_label (join_bb)));
634
  SET_EXPR_LOCUS (t, locus);
635
  tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
636
 
637
  /* At this point, after so much hard work, we have only constructed
638
     the conditional jump,
639
 
640
     if (__mf_elem->low > __mf_base
641
         || (__mf_elem_high < __mf_limit))
642
 
643
     The lowered GIMPLE tree representing this code is in the statement
644
     list starting at 'head'.
645
 
646
     We can insert this now in the current basic block, i.e. the one that
647
     the statement we're instrumenting was originally in.  */
648
  bsi = bsi_last (cond_bb);
649
  for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
650
    bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
651
 
652
  /*  Now build up the body of the cache-miss handling:
653
 
654
     __mf_check();
655
     refresh *_l vars.
656
 
657
     This is the body of the conditional.  */
658
 
659
  u = tree_cons (NULL_TREE,
660
                 mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION
661
                                             : *locus),
662
                 NULL_TREE);
663
  u = tree_cons (NULL_TREE, dirflag, u);
664
  /* NB: we pass the overall [base..limit] range to mf_check.  */
665
  u = tree_cons (NULL_TREE,
666
                 fold_build2 (PLUS_EXPR, integer_type_node,
667
                              fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base),
668
                              integer_one_node),
669
                 u);
670
  u = tree_cons (NULL_TREE, mf_base, u);
671
  t = build_function_call_expr (mf_check_fndecl, u);
672
  gimplify_to_stmt_list (&t);
673
  head = tsi_start (t);
674
  tsi = tsi_last (t);
675
 
676
  if (! flag_mudflap_threads)
677
    {
678
      t = build2 (MODIFY_EXPR, void_type_node,
679
                  mf_cache_shift_decl_l, mf_cache_shift_decl);
680
      tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
681
 
682
      t = build2 (MODIFY_EXPR, void_type_node,
683
                  mf_cache_mask_decl_l, mf_cache_mask_decl);
684
      tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
685
    }
686
 
687
  /* Insert the check code in the THEN block.  */
688
  bsi = bsi_start (then_bb);
689
  for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
690
    bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
691
 
692
  *instr_bsi = bsi_start (join_bb);
693
  bsi_next (instr_bsi);
694
}
695
 
696
 
697
/* Check whether the given decl, generally a VAR_DECL or PARM_DECL, is
698
   eligible for instrumentation.  For the mudflap1 pass, this implies
699
   that it should be registered with the libmudflap runtime.  For the
700
   mudflap2 pass this means instrumenting an indirection operation with
701
   respect to the object.
702
*/
703
static int
704
mf_decl_eligible_p (tree decl)
705
{
706
  return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
707
          /* The decl must have its address taken.  In the case of
708
             arrays, this flag is also set if the indexes are not
709
             compile-time known valid constants.  */
710
          && TREE_ADDRESSABLE (decl)    /* XXX: not sufficient: return-by-value structs! */
711
          /* The type of the variable must be complete.  */
712
          && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
713
          /* The decl hasn't been decomposed somehow.  */
714
          && !DECL_HAS_VALUE_EXPR_P (decl));
715
}
716
 
717
 
718
static void
719
mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
720
                   location_t *locus, tree dirflag)
721
{
722
  tree type, base, limit, addr, size, t;
723
 
724
  /* Don't instrument read operations.  */
725
  if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
726
    return;
727
 
728
  /* Don't instrument marked nodes.  */
729
  if (mf_marked_p (*tp))
730
    return;
731
 
732
  t = *tp;
733
  type = TREE_TYPE (t);
734
 
735
  if (type == error_mark_node)
736
    return;
737
 
738
  size = TYPE_SIZE_UNIT (type);
739
 
740
  switch (TREE_CODE (t))
741
    {
742
    case ARRAY_REF:
743
    case COMPONENT_REF:
744
      {
745
        /* This is trickier than it may first appear.  The reason is
746
           that we are looking at expressions from the "inside out" at
747
           this point.  We may have a complex nested aggregate/array
748
           expression (e.g. "a.b[i].c"), maybe with an indirection as
749
           the leftmost operator ("p->a.b.d"), where instrumentation
750
           is necessary.  Or we may have an innocent "a.b.c"
751
           expression that must not be instrumented.  We need to
752
           recurse all the way down the nesting structure to figure it
753
           out: looking just at the outer node is not enough.  */
754
        tree var;
755
        int component_ref_only = (TREE_CODE (t) == COMPONENT_REF);
756
        /* If we have a bitfield component reference, we must note the
757
           innermost addressable object in ELT, from which we will
758
           construct the byte-addressable bounds of the bitfield.  */
759
        tree elt = NULL_TREE;
760
        int bitfield_ref_p = (TREE_CODE (t) == COMPONENT_REF
761
                              && DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1)));
762
 
763
        /* Iterate to the top of the ARRAY_REF/COMPONENT_REF
764
           containment hierarchy to find the outermost VAR_DECL.  */
765
        var = TREE_OPERAND (t, 0);
766
        while (1)
767
          {
768
            if (bitfield_ref_p && elt == NULL_TREE
769
                && (TREE_CODE (var) == ARRAY_REF || TREE_CODE (var) == COMPONENT_REF))
770
              elt = var;
771
 
772
            if (TREE_CODE (var) == ARRAY_REF)
773
              {
774
                component_ref_only = 0;
775
                var = TREE_OPERAND (var, 0);
776
              }
777
            else if (TREE_CODE (var) == COMPONENT_REF)
778
              var = TREE_OPERAND (var, 0);
779
            else if (INDIRECT_REF_P (var))
780
              {
781
                base = TREE_OPERAND (var, 0);
782
                break;
783
              }
784
            else
785
              {
786
                gcc_assert (TREE_CODE (var) == VAR_DECL
787
                            || TREE_CODE (var) == PARM_DECL
788
                            || TREE_CODE (var) == RESULT_DECL
789
                            || TREE_CODE (var) == STRING_CST);
790
                /* Don't instrument this access if the underlying
791
                   variable is not "eligible".  This test matches
792
                   those arrays that have only known-valid indexes,
793
                   and thus are not labeled TREE_ADDRESSABLE.  */
794
                if (! mf_decl_eligible_p (var) || component_ref_only)
795
                  return;
796
                else
797
                  {
798
                    base = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (var)), var);
799
                    break;
800
                  }
801
              }
802
          }
803
 
804
        /* Handle the case of ordinary non-indirection structure
805
           accesses.  These have only nested COMPONENT_REF nodes (no
806
           INDIRECT_REF), but pass through the above filter loop.
807
           Note that it's possible for such a struct variable to match
808
           the eligible_p test because someone else might take its
809
           address sometime.  */
810
 
811
        /* We need special processing for bitfield components, because
812
           their addresses cannot be taken.  */
813
        if (bitfield_ref_p)
814
          {
815
            tree field = TREE_OPERAND (t, 1);
816
 
817
            if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
818
              size = DECL_SIZE_UNIT (field);
819
 
820
            if (elt)
821
              elt = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (elt)), elt);
822
            addr = fold_convert (ptr_type_node, elt ? elt : base);
823
            addr = fold_build2 (PLUS_EXPR, ptr_type_node,
824
                                addr, fold_convert (ptr_type_node,
825
                                                    byte_position (field)));
826
          }
827
        else
828
          addr = build1 (ADDR_EXPR, build_pointer_type (type), t);
829
 
830
        limit = fold_build2 (MINUS_EXPR, mf_uintptr_type,
831
                             fold_build2 (PLUS_EXPR, mf_uintptr_type,
832
                                          convert (mf_uintptr_type, addr),
833
                                          size),
834
                             integer_one_node);
835
      }
836
      break;
837
 
838
    case INDIRECT_REF:
839
      addr = TREE_OPERAND (t, 0);
840
      base = addr;
841
      limit = fold_build2 (MINUS_EXPR, ptr_type_node,
842
                           fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
843
                           integer_one_node);
844
      break;
845
 
846
    case TARGET_MEM_REF:
847
      addr = tree_mem_ref_addr (ptr_type_node, t);
848
      base = addr;
849
      limit = fold_build2 (MINUS_EXPR, ptr_type_node,
850
                           fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
851
                           build_int_cst (ptr_type_node, 1));
852
      break;
853
 
854
    case ARRAY_RANGE_REF:
855
      warning (0, "mudflap checking not yet implemented for ARRAY_RANGE_REF");
856
      return;
857
 
858
    case BIT_FIELD_REF:
859
      /* ??? merge with COMPONENT_REF code above? */
860
      {
861
        tree ofs, rem, bpu;
862
 
863
        /* If we're not dereferencing something, then the access
864
           must be ok.  */
865
        if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
866
          return;
867
 
868
        bpu = bitsize_int (BITS_PER_UNIT);
869
        ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
870
        rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
871
        ofs = size_binop (TRUNC_DIV_EXPR, ofs, bpu);
872
 
873
        size = convert (bitsizetype, TREE_OPERAND (t, 1));
874
        size = size_binop (PLUS_EXPR, size, rem);
875
        size = size_binop (CEIL_DIV_EXPR, size, bpu);
876
        size = convert (sizetype, size);
877
 
878
        addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
879
        addr = convert (ptr_type_node, addr);
880
        addr = fold_build2 (PLUS_EXPR, ptr_type_node, addr, ofs);
881
 
882
        base = addr;
883
        limit = fold_build2 (MINUS_EXPR, ptr_type_node,
884
                             fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
885
                             integer_one_node);
886
      }
887
      break;
888
 
889
    default:
890
      return;
891
    }
892
 
893
  mf_build_check_statement_for (base, limit, iter, locus, dirflag);
894
}
895
 
896
static void
897
mf_xform_derefs (void)
898
{
899
  basic_block bb, next;
900
  block_stmt_iterator i;
901
  int saved_last_basic_block = last_basic_block;
902
 
903
  bb = ENTRY_BLOCK_PTR ->next_bb;
904
  do
905
    {
906
      next = bb->next_bb;
907
      for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
908
        {
909
          tree s = bsi_stmt (i);
910
 
911
          /* Only a few GIMPLE statements can reference memory.  */
912
          switch (TREE_CODE (s))
913
            {
914
            case MODIFY_EXPR:
915
              mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
916
                                 integer_one_node);
917
              mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 1), EXPR_LOCUS (s),
918
                                 integer_zero_node);
919
              break;
920
 
921
            case RETURN_EXPR:
922
              if (TREE_OPERAND (s, 0) != NULL_TREE)
923
                {
924
                  if (TREE_CODE (TREE_OPERAND (s, 0)) == MODIFY_EXPR)
925
                    mf_xform_derefs_1 (&i, &TREE_OPERAND (TREE_OPERAND (s, 0), 1),
926
                                       EXPR_LOCUS (s), integer_zero_node);
927
                  else
928
                    mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
929
                                       integer_zero_node);
930
                }
931
              break;
932
 
933
            default:
934
              ;
935
            }
936
        }
937
      bb = next;
938
    }
939
  while (bb && bb->index <= saved_last_basic_block);
940
}
941
 
942
/* ------------------------------------------------------------------------ */
943
/* ADDR_EXPR transforms.  Perform the declaration-related mudflap tree
944
   transforms on the current function.
945
 
946
   This is the first part of the mudflap instrumentation.  It works on
947
   high-level GIMPLE because after lowering, all variables are moved out
948
   of their BIND_EXPR binding context, and we lose liveness information
949
   for the declarations we wish to instrument.  */
950
 
951
static unsigned int
952
execute_mudflap_function_decls (void)
953
{
954
  /* Don't instrument functions such as the synthetic constructor
955
     built during mudflap_finish_file.  */
956
  if (mf_marked_p (current_function_decl) ||
957
      DECL_ARTIFICIAL (current_function_decl))
958
    return 0;
959
 
960
  push_gimplify_context ();
961
 
962
  mf_xform_decls (DECL_SAVED_TREE (current_function_decl),
963
                  DECL_ARGUMENTS (current_function_decl));
964
 
965
  pop_gimplify_context (NULL);
966
  return 0;
967
}
968
 
969
/* This struct is passed between mf_xform_decls to store state needed
970
   during the traversal searching for objects that have their
971
   addresses taken.  */
972
struct mf_xform_decls_data
973
{
974
  tree param_decls;
975
};
976
 
977
 
978
/* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
979
   _DECLs if appropriate.  Arrange to call the __mf_register function
980
   now, and the __mf_unregister function later for each.  */
981
static void
982
mx_register_decls (tree decl, tree *stmt_list)
983
{
984
  tree finally_stmts = NULL_TREE;
985
  tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);
986
 
987
  while (decl != NULL_TREE)
988
    {
989
      if (mf_decl_eligible_p (decl)
990
          /* Not already processed.  */
991
          && ! mf_marked_p (decl)
992
          /* Automatic variable.  */
993
          && ! DECL_EXTERNAL (decl)
994
          && ! TREE_STATIC (decl))
995
        {
996
          tree size = NULL_TREE, variable_name;
997
          tree unregister_fncall, unregister_fncall_params;
998
          tree register_fncall, register_fncall_params;
999
 
1000
          size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
1001
 
1002
          /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
1003
          unregister_fncall_params =
1004
            tree_cons (NULL_TREE,
1005
                       convert (ptr_type_node,
1006
                                mf_mark (build1 (ADDR_EXPR,
1007
                                                 build_pointer_type (TREE_TYPE (decl)),
1008
                                                 decl))),
1009
                       tree_cons (NULL_TREE,
1010
                                  size,
1011
                                  tree_cons (NULL_TREE,
1012
                                             /* __MF_TYPE_STACK */
1013
                                             build_int_cst (NULL_TREE, 3),
1014
                                             NULL_TREE)));
1015
          /* __mf_unregister (...) */
1016
          unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
1017
                                                        unregister_fncall_params);
1018
 
1019
          /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */
1020
          variable_name = mf_varname_tree (decl);
1021
          register_fncall_params =
1022
            tree_cons (NULL_TREE,
1023
                   convert (ptr_type_node,
1024
                            mf_mark (build1 (ADDR_EXPR,
1025
                                             build_pointer_type (TREE_TYPE (decl)),
1026
                                             decl))),
1027
                       tree_cons (NULL_TREE,
1028
                                  size,
1029
                                  tree_cons (NULL_TREE,
1030
                                             /* __MF_TYPE_STACK */
1031
                                             build_int_cst (NULL_TREE, 3),
1032
                                             tree_cons (NULL_TREE,
1033
                                                        variable_name,
1034
                                                        NULL_TREE))));
1035
 
1036
          /* __mf_register (...) */
1037
          register_fncall = build_function_call_expr (mf_register_fndecl,
1038
                                                      register_fncall_params);
1039
 
1040
          /* Accumulate the two calls.  */
1041
          /* ??? Set EXPR_LOCATION.  */
1042
          gimplify_stmt (&register_fncall);
1043
          gimplify_stmt (&unregister_fncall);
1044
 
1045
          /* Add the __mf_register call at the current appending point.  */
1046
          if (tsi_end_p (initially_stmts))
1047
            warning (0, "mudflap cannot track %qs in stub function",
1048
                     IDENTIFIER_POINTER (DECL_NAME (decl)));
1049
          else
1050
            {
1051
              tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);
1052
 
1053
              /* Accumulate the FINALLY piece.  */
1054
              append_to_statement_list (unregister_fncall, &finally_stmts);
1055
            }
1056
          mf_mark (decl);
1057
        }
1058
 
1059
      decl = TREE_CHAIN (decl);
1060
    }
1061
 
1062
  /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
1063
  if (finally_stmts != NULL_TREE)
1064
    {
1065
      tree t = build2 (TRY_FINALLY_EXPR, void_type_node,
1066
                       *stmt_list, finally_stmts);
1067
      *stmt_list = NULL;
1068
      append_to_statement_list (t, stmt_list);
1069
    }
1070
}
1071
 
1072
 
1073
/* Process every variable mentioned in BIND_EXPRs.  */
1074
static tree
1075
mx_xfn_xform_decls (tree *t, int *continue_p, void *data)
1076
{
1077
  struct mf_xform_decls_data* d = (struct mf_xform_decls_data*) data;
1078
 
1079
  if (*t == NULL_TREE || *t == error_mark_node)
1080
    {
1081
      *continue_p = 0;
1082
      return NULL_TREE;
1083
    }
1084
 
1085
  *continue_p = 1;
1086
 
1087
  switch (TREE_CODE (*t))
1088
    {
1089
    case BIND_EXPR:
1090
      {
1091
        /* Process function parameters now (but only once).  */
1092
        mx_register_decls (d->param_decls, &BIND_EXPR_BODY (*t));
1093
        d->param_decls = NULL_TREE;
1094
 
1095
        mx_register_decls (BIND_EXPR_VARS (*t), &BIND_EXPR_BODY (*t));
1096
      }
1097
      break;
1098
 
1099
    default:
1100
      break;
1101
    }
1102
 
1103
  return NULL_TREE;
1104
}
1105
 
1106
/* Perform the object lifetime tracking mudflap transform on the given function
1107
   tree.  The tree is mutated in place, with possibly copied subtree nodes.
1108
 
1109
   For every auto variable declared, if its address is ever taken
1110
   within the function, then supply its lifetime to the mudflap
1111
   runtime with the __mf_register and __mf_unregister calls.
1112
*/
1113
 
1114
static void
1115
mf_xform_decls (tree fnbody, tree fnparams)
1116
{
1117
  struct mf_xform_decls_data d;
1118
  d.param_decls = fnparams;
1119
  walk_tree_without_duplicates (&fnbody, mx_xfn_xform_decls, &d);
1120
}
1121
 
1122
 
1123
/* ------------------------------------------------------------------------ */
1124
/* Externally visible mudflap functions.  */
1125
 
1126
 
1127
/* Mark and return the given tree node to prevent further mudflap
1128
   transforms.  */
1129
static GTY ((param_is (union tree_node))) htab_t marked_trees = NULL;
1130
 
1131
tree
1132
mf_mark (tree t)
1133
{
1134
  void **slot;
1135
 
1136
  if (marked_trees == NULL)
1137
    marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer, NULL);
1138
 
1139
  slot = htab_find_slot (marked_trees, t, INSERT);
1140
  *slot = t;
1141
  return t;
1142
}
1143
 
1144
int
1145
mf_marked_p (tree t)
1146
{
1147
  void *entry;
1148
 
1149
  if (marked_trees == NULL)
1150
    return 0;
1151
 
1152
  entry = htab_find (marked_trees, t);
1153
  return (entry != NULL);
1154
}
1155
 
1156
/* Remember given node as a static of some kind: global data,
1157
   function-scope static, or an anonymous constant.  Its assembler
1158
   label is given.  */
1159
 
1160
/* A list of globals whose incomplete declarations we encountered.
1161
   Instead of emitting the __mf_register call for them here, it's
1162
   delayed until program finish time.  If they're still incomplete by
1163
   then, warnings are emitted.  */
1164
 
1165
static GTY (()) VEC(tree,gc) *deferred_static_decls;
1166
 
1167
/* A list of statements for calling __mf_register() at startup time.  */
1168
static GTY (()) tree enqueued_call_stmt_chain;
1169
 
1170
static void
1171
mudflap_register_call (tree obj, tree object_size, tree varname)
1172
{
1173
  tree arg, args, call_stmt;
1174
 
1175
  args = tree_cons (NULL_TREE, varname, NULL_TREE);
1176
 
1177
  arg = build_int_cst (NULL_TREE, 4); /* __MF_TYPE_STATIC */
1178
  args = tree_cons (NULL_TREE, arg, args);
1179
 
1180
  arg = convert (size_type_node, object_size);
1181
  args = tree_cons (NULL_TREE, arg, args);
1182
 
1183
  arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
1184
  arg = convert (ptr_type_node, arg);
1185
  args = tree_cons (NULL_TREE, arg, args);
1186
 
1187
  call_stmt = build_function_call_expr (mf_register_fndecl, args);
1188
 
1189
  append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
1190
}
1191
 
1192
void
1193
mudflap_enqueue_decl (tree obj)
1194
{
1195
  if (mf_marked_p (obj))
1196
    return;
1197
 
1198
  /* We don't need to process variable decls that are internally
1199
     generated extern.  If we did, we'd end up with warnings for them
1200
     during mudflap_finish_file ().  That would confuse the user,
1201
     since the text would refer to variables that don't show up in the
1202
     user's source code.  */
1203
  if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj))
1204
    return;
1205
 
1206
  VEC_safe_push (tree, gc, deferred_static_decls, obj);
1207
}
1208
 
1209
 
1210
void
1211
mudflap_enqueue_constant (tree obj)
1212
{
1213
  tree object_size, varname;
1214
 
1215
  if (mf_marked_p (obj))
1216
    return;
1217
 
1218
  if (TREE_CODE (obj) == STRING_CST)
1219
    object_size = build_int_cst (NULL_TREE, TREE_STRING_LENGTH (obj));
1220
  else
1221
    object_size = size_in_bytes (TREE_TYPE (obj));
1222
 
1223
  if (TREE_CODE (obj) == STRING_CST)
1224
    varname = mf_build_string ("string literal");
1225
  else
1226
    varname = mf_build_string ("constant");
1227
 
1228
  mudflap_register_call (obj, object_size, varname);
1229
}
1230
 
1231
 
1232
/* Emit any file-wide instrumentation.  */
1233
void
1234
mudflap_finish_file (void)
1235
{
1236
  tree ctor_statements = NULL_TREE;
1237
 
1238
  /* No need to continue when there were errors.  */
1239
  if (errorcount != 0 || sorrycount != 0)
1240
    return;
1241
 
1242
  /* Insert a call to __mf_init.  */
1243
  {
1244
    tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
1245
    append_to_statement_list (call2_stmt, &ctor_statements);
1246
  }
1247
 
1248
  /* If appropriate, call __mf_set_options to pass along read-ignore mode.  */
1249
  if (flag_mudflap_ignore_reads)
1250
    {
1251
      tree arg = tree_cons (NULL_TREE,
1252
                            mf_build_string ("-ignore-reads"), NULL_TREE);
1253
      tree call_stmt = build_function_call_expr (mf_set_options_fndecl, arg);
1254
      append_to_statement_list (call_stmt, &ctor_statements);
1255
    }
1256
 
1257
  /* Process all enqueued object decls.  */
1258
  if (deferred_static_decls)
1259
    {
1260
      size_t i;
1261
      tree obj;
1262
      for (i = 0; VEC_iterate (tree, deferred_static_decls, i, obj); i++)
1263
        {
1264
          gcc_assert (DECL_P (obj));
1265
 
1266
          if (mf_marked_p (obj))
1267
            continue;
1268
 
1269
          /* Omit registration for static unaddressed objects.  NB:
1270
             Perform registration for non-static objects regardless of
1271
             TREE_USED or TREE_ADDRESSABLE, because they may be used
1272
             from other compilation units.  */
1273
          if (! TREE_PUBLIC (obj) && ! TREE_ADDRESSABLE (obj))
1274
            continue;
1275
 
1276
          if (! COMPLETE_TYPE_P (TREE_TYPE (obj)))
1277
            {
1278
              warning (0, "mudflap cannot track unknown size extern %qs",
1279
                       IDENTIFIER_POINTER (DECL_NAME (obj)));
1280
              continue;
1281
            }
1282
 
1283
          mudflap_register_call (obj,
1284
                                 size_in_bytes (TREE_TYPE (obj)),
1285
                                 mf_varname_tree (obj));
1286
        }
1287
 
1288
      VEC_truncate (tree, deferred_static_decls, 0);
1289
    }
1290
 
1291
  /* Append all the enqueued registration calls.  */
1292
  if (enqueued_call_stmt_chain)
1293
    {
1294
      append_to_statement_list (enqueued_call_stmt_chain, &ctor_statements);
1295
      enqueued_call_stmt_chain = NULL_TREE;
1296
    }
1297
 
1298
  cgraph_build_static_cdtor ('I', ctor_statements,
1299
                             MAX_RESERVED_INIT_PRIORITY-1);
1300
}
1301
 
1302
 
1303
static bool
1304
gate_mudflap (void)
1305
{
1306
  return flag_mudflap != 0;
1307
}
1308
 
1309
struct tree_opt_pass pass_mudflap_1 =
1310
{
1311
  "mudflap1",                           /* name */
1312
  gate_mudflap,                         /* gate */
1313
  execute_mudflap_function_decls,       /* execute */
1314
  NULL,                                 /* sub */
1315
  NULL,                                 /* next */
1316
  0,                                    /* static_pass_number */
1317
  0,                                    /* tv_id */
1318
  PROP_gimple_any,                      /* properties_required */
1319
  0,                                    /* properties_provided */
1320
  0,                                    /* properties_destroyed */
1321
  0,                                    /* todo_flags_start */
1322
  TODO_dump_func,                       /* todo_flags_finish */
1323
 
1324
};
1325
 
1326
struct tree_opt_pass pass_mudflap_2 =
1327
{
1328
  "mudflap2",                           /* name */
1329
  gate_mudflap,                         /* gate */
1330
  execute_mudflap_function_ops,         /* execute */
1331
  NULL,                                 /* sub */
1332
  NULL,                                 /* next */
1333
  0,                                    /* static_pass_number */
1334
  0,                                    /* tv_id */
1335
  PROP_gimple_leh,                      /* properties_required */
1336
  0,                                    /* properties_provided */
1337
  0,                                    /* properties_destroyed */
1338
  0,                                    /* todo_flags_start */
1339
  TODO_verify_flow | TODO_verify_stmts
1340
  | TODO_dump_func,                     /* todo_flags_finish */
1341
 
1342
};
1343
 
1344
#include "gt-tree-mudflap.h"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.