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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [tree-mudflap.c] - Blame information for rev 826

Details | Compare with Previous | View Log

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