2015-03-02 Hristian Kirtchev <kirtchev@adacore.com>
[official-gcc.git] / gcc / ipa-chkp.c
blob0b857ffb8a05098f0a5b54329981fea96fcdff1b
1 /* Pointer Bounds Checker IPA passes.
2 Copyright (C) 2014-2015 Free Software Foundation, Inc.
3 Contributed by Ilya Enkovich (ilya.enkovich@intel.com)
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "hash-set.h"
25 #include "machmode.h"
26 #include "vec.h"
27 #include "double-int.h"
28 #include "input.h"
29 #include "alias.h"
30 #include "symtab.h"
31 #include "options.h"
32 #include "wide-int.h"
33 #include "inchash.h"
34 #include "tree.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
37 #include "tree-pass.h"
38 #include "stringpool.h"
39 #include "bitmap.h"
40 #include "gimple-expr.h"
41 #include "tm.h"
42 #include "hard-reg-set.h"
43 #include "function.h"
44 #include "is-a.h"
45 #include "tree-ssa-alias.h"
46 #include "predict.h"
47 #include "basic-block.h"
48 #include "gimple.h"
49 #include "ipa-ref.h"
50 #include "lto-streamer.h"
51 #include "cgraph.h"
52 #include "tree-chkp.h"
53 #include "tree-inline.h"
54 #include "ipa-chkp.h"
56 /* Pointer Bounds Checker has two IPA passes to support code instrumentation.
58 In instrumented code each pointer is provided with bounds. For input
59 pointer parameters it means we also have bounds passed. For calls it
60 means we have additional bounds arguments for pointer arguments.
62 To have all IPA optimizations working correctly we have to express
63 dataflow between passed and received bounds explicitly via additional
64 entries in function declaration arguments list and in function type.
65 Since we may have both instrumented and not instrumented code at the
66 same time, we cannot replace all original functions with their
67 instrumented variants. Therefore we create clones (versions) instead.
69 Instrumentation clones creation is a separate IPA pass which is a part
70 of early local passes. Clones are created after SSA is built (because
71 instrumentation pass works on SSA) and before any transformations
72 which may change pointer flow and therefore lead to incorrect code
73 instrumentation (possibly causing false bounds check failures).
75 Instrumentation clones have pointer bounds arguments added right after
76 pointer arguments. Clones have assembler name of the original
77 function with suffix added. New assembler name is in transparent
78 alias chain with the original name. Thus we expect all calls to the
79 original and instrumented functions look similar in assembler.
81 During instrumentation versioning pass we create instrumented versions
82 of all function with body and also for all their aliases and thunks.
83 Clones for functions with no body are created on demand (usually
84 during call instrumentation).
86 Original and instrumented function nodes are connected with IPA
87 reference IPA_REF_CHKP. It is mostly done to have reachability
88 analysis working correctly. We may have no references to the
89 instrumented function in the code but it still should be counted
90 as reachable if the original function is reachable.
92 When original function bodies are not needed anymore we release
93 them and transform functions into a special kind of thunks. Each
94 thunk has a call edge to the instrumented version. These thunks
95 help to keep externally visible instrumented functions visible
96 when linker resolution files are used. Linker has no info about
97 connection between original and instrumented function and
98 therefore we may wrongly decide (due to difference in assembler
99 names) that instrumented function version is local and can be
100 removed. */
102 #define CHKP_BOUNDS_OF_SYMBOL_PREFIX "__chkp_bounds_of_"
104 /* Build a clone of FNDECL with a modified name. */
106 static tree
107 chkp_build_instrumented_fndecl (tree fndecl)
109 tree new_decl = copy_node (fndecl);
110 tree new_name;
111 std::string s;
113 /* called_as_built_in checks DECL_NAME to identify calls to
114 builtins. We want instrumented calls to builtins to be
115 recognized by called_as_built_in. Therefore use original
116 DECL_NAME for cloning with no prefixes. */
117 s = IDENTIFIER_POINTER (DECL_NAME (fndecl));
118 s += ".chkp";
119 DECL_NAME (new_decl) = get_identifier (s.c_str ());
121 /* References to the original and to the instrumented version
122 should look the same in the output assembly. And we cannot
123 use the same assembler name for the instrumented version
124 because it conflicts with decl merging algorithms in LTO.
125 Achieve the result by using transparent alias name for the
126 instrumented version. */
127 s = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl));
128 s += ".chkp";
129 new_name = get_identifier (s.c_str ());
130 IDENTIFIER_TRANSPARENT_ALIAS (new_name) = 1;
131 TREE_CHAIN (new_name) = DECL_ASSEMBLER_NAME (fndecl);
132 SET_DECL_ASSEMBLER_NAME (new_decl, new_name);
134 /* For functions with body versioning will make a copy of arguments.
135 For functions with no body we need to do it here. */
136 if (!gimple_has_body_p (fndecl))
137 DECL_ARGUMENTS (new_decl) = copy_list (DECL_ARGUMENTS (fndecl));
139 /* We are going to modify attributes list and therefore should
140 make own copy. */
141 DECL_ATTRIBUTES (new_decl) = copy_list (DECL_ATTRIBUTES (fndecl));
143 /* Change builtin function code. */
144 if (DECL_BUILT_IN (new_decl))
146 gcc_assert (DECL_BUILT_IN_CLASS (new_decl) == BUILT_IN_NORMAL);
147 gcc_assert (DECL_FUNCTION_CODE (new_decl) < BEGIN_CHKP_BUILTINS);
148 DECL_FUNCTION_CODE (new_decl)
149 = (enum built_in_function)(DECL_FUNCTION_CODE (new_decl)
150 + BEGIN_CHKP_BUILTINS + 1);
153 return new_decl;
157 /* Fix operands of attribute from ATTRS list named ATTR_NAME.
158 Integer operands are replaced with values according to
159 INDEXES map having LEN elements. For operands out of len
160 we just add DELTA. */
162 static void
163 chkp_map_attr_arg_indexes (tree attrs, const char *attr_name,
164 unsigned *indexes, int len, int delta)
166 tree attr = lookup_attribute (attr_name, attrs);
167 tree op;
169 if (!attr)
170 return;
172 TREE_VALUE (attr) = copy_list (TREE_VALUE (attr));
173 for (op = TREE_VALUE (attr); op; op = TREE_CHAIN (op))
175 int idx;
177 if (TREE_CODE (TREE_VALUE (op)) != INTEGER_CST)
178 continue;
180 idx = TREE_INT_CST_LOW (TREE_VALUE (op));
182 /* If idx exceeds indexes length then we just
183 keep it at the same distance from the last
184 known arg. */
185 if (idx > len)
186 idx += delta;
187 else
188 idx = indexes[idx - 1] + 1;
189 TREE_VALUE (op) = build_int_cst (TREE_TYPE (TREE_VALUE (op)), idx);
193 /* Make a copy of function type ORIG_TYPE adding pointer
194 bounds as additional arguments. */
196 tree
197 chkp_copy_function_type_adding_bounds (tree orig_type)
199 tree type;
200 tree arg_type, attrs, t;
201 unsigned len = list_length (TYPE_ARG_TYPES (orig_type));
202 unsigned *indexes = XALLOCAVEC (unsigned, len);
203 unsigned idx = 0, new_idx = 0;
205 for (arg_type = TYPE_ARG_TYPES (orig_type);
206 arg_type;
207 arg_type = TREE_CHAIN (arg_type))
208 if (TREE_VALUE (arg_type) == void_type_node)
209 continue;
210 else if (BOUNDED_TYPE_P (TREE_VALUE (arg_type))
211 || pass_by_reference (NULL, TYPE_MODE (TREE_VALUE (arg_type)),
212 TREE_VALUE (arg_type), true)
213 || chkp_type_has_pointer (TREE_VALUE (arg_type)))
214 break;
216 /* We may use original type if there are no bounds passed. */
217 if (!arg_type)
218 return orig_type;
220 type = copy_node (orig_type);
221 TYPE_ARG_TYPES (type) = copy_list (TYPE_ARG_TYPES (type));
223 for (arg_type = TYPE_ARG_TYPES (type);
224 arg_type;
225 arg_type = TREE_CHAIN (arg_type))
227 indexes[idx++] = new_idx++;
229 /* pass_by_reference returns 1 for void type,
230 so check for it first. */
231 if (TREE_VALUE (arg_type) == void_type_node)
232 continue;
233 else if (BOUNDED_TYPE_P (TREE_VALUE (arg_type))
234 || pass_by_reference (NULL, TYPE_MODE (TREE_VALUE (arg_type)),
235 TREE_VALUE (arg_type), true))
237 tree new_type = build_tree_list (NULL_TREE,
238 pointer_bounds_type_node);
239 TREE_CHAIN (new_type) = TREE_CHAIN (arg_type);
240 TREE_CHAIN (arg_type) = new_type;
242 arg_type = TREE_CHAIN (arg_type);
243 new_idx++;
245 else if (chkp_type_has_pointer (TREE_VALUE (arg_type)))
247 bitmap slots = BITMAP_ALLOC (NULL);
248 bitmap_iterator bi;
249 unsigned bnd_no;
251 chkp_find_bound_slots (TREE_VALUE (arg_type), slots);
253 EXECUTE_IF_SET_IN_BITMAP (slots, 0, bnd_no, bi)
255 tree new_type = build_tree_list (NULL_TREE,
256 pointer_bounds_type_node);
257 TREE_CHAIN (new_type) = TREE_CHAIN (arg_type);
258 TREE_CHAIN (arg_type) = new_type;
260 arg_type = TREE_CHAIN (arg_type);
261 new_idx++;
263 BITMAP_FREE (slots);
267 /* If function type has attribute with arg indexes then
268 we have to copy it fixing attribute ops. Map for
269 fixing is in indexes array. */
270 attrs = TYPE_ATTRIBUTES (type);
271 if (lookup_attribute ("nonnull", attrs)
272 || lookup_attribute ("format", attrs)
273 || lookup_attribute ("format_arg", attrs))
275 int delta = new_idx - len;
276 attrs = copy_list (TYPE_ATTRIBUTES (type));
277 chkp_map_attr_arg_indexes (attrs, "nonnull", indexes, len, delta);
278 chkp_map_attr_arg_indexes (attrs, "format", indexes, len, delta);
279 chkp_map_attr_arg_indexes (attrs, "format_arg", indexes, len, delta);
280 TYPE_ATTRIBUTES (type) = attrs;
283 t = TYPE_MAIN_VARIANT (orig_type);
284 if (orig_type != t)
286 TYPE_MAIN_VARIANT (type) = t;
287 TYPE_NEXT_VARIANT (type) = TYPE_NEXT_VARIANT (t);
288 TYPE_NEXT_VARIANT (t) = type;
290 else
292 TYPE_MAIN_VARIANT (type) = type;
293 TYPE_NEXT_VARIANT (type) = NULL;
297 return type;
300 /* For given function FNDECL add bounds arguments to arguments
301 list. */
303 static void
304 chkp_add_bounds_params_to_function (tree fndecl)
306 tree arg;
308 for (arg = DECL_ARGUMENTS (fndecl); arg; arg = DECL_CHAIN (arg))
309 if (BOUNDED_P (arg))
311 std::string new_name = CHKP_BOUNDS_OF_SYMBOL_PREFIX;
312 tree new_arg;
314 if (DECL_NAME (arg))
315 new_name += IDENTIFIER_POINTER (DECL_NAME (arg));
316 else
318 char uid[25];
319 snprintf (uid, 25, "D.%u", DECL_UID (arg));
320 new_name += uid;
323 new_arg = build_decl (DECL_SOURCE_LOCATION (arg), PARM_DECL,
324 get_identifier (new_name.c_str ()),
325 pointer_bounds_type_node);
326 DECL_ARG_TYPE (new_arg) = pointer_bounds_type_node;
327 DECL_CONTEXT (new_arg) = DECL_CONTEXT (arg);
328 DECL_ARTIFICIAL (new_arg) = 1;
329 DECL_CHAIN (new_arg) = DECL_CHAIN (arg);
330 DECL_CHAIN (arg) = new_arg;
332 arg = DECL_CHAIN (arg);
335 else if (chkp_type_has_pointer (TREE_TYPE (arg)))
337 tree orig_arg = arg;
338 bitmap slots = BITMAP_ALLOC (NULL);
339 bitmap_iterator bi;
340 unsigned bnd_no;
342 chkp_find_bound_slots (TREE_TYPE (arg), slots);
344 EXECUTE_IF_SET_IN_BITMAP (slots, 0, bnd_no, bi)
346 std::string new_name = CHKP_BOUNDS_OF_SYMBOL_PREFIX;
347 tree new_arg;
348 char offs[25];
350 if (DECL_NAME (orig_arg))
351 new_name += IDENTIFIER_POINTER (DECL_NAME (orig_arg));
352 else
354 snprintf (offs, 25, "D.%u", DECL_UID (arg));
355 new_name += offs;
357 snprintf (offs, 25, "__%u", bnd_no * POINTER_SIZE / BITS_PER_UNIT);
359 new_arg = build_decl (DECL_SOURCE_LOCATION (orig_arg),
360 PARM_DECL,
361 get_identifier (new_name.c_str ()),
362 pointer_bounds_type_node);
363 DECL_ARG_TYPE (new_arg) = pointer_bounds_type_node;
364 DECL_CONTEXT (new_arg) = DECL_CONTEXT (orig_arg);
365 DECL_ARTIFICIAL (new_arg) = 1;
366 DECL_CHAIN (new_arg) = DECL_CHAIN (arg);
367 DECL_CHAIN (arg) = new_arg;
369 arg = DECL_CHAIN (arg);
371 BITMAP_FREE (slots);
374 TREE_TYPE (fndecl) =
375 chkp_copy_function_type_adding_bounds (TREE_TYPE (fndecl));
378 /* Return an instrumentation clone for builtin function
379 FNDECL. Create one if needed. */
381 tree
382 chkp_maybe_clone_builtin_fndecl (tree fndecl)
384 tree clone;
385 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
387 gcc_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
388 && fcode < BEGIN_CHKP_BUILTINS);
390 fcode = (enum built_in_function) (fcode + BEGIN_CHKP_BUILTINS + 1);
391 clone = builtin_decl_explicit (fcode);
392 if (clone)
393 return clone;
395 clone = chkp_build_instrumented_fndecl (fndecl);
396 chkp_add_bounds_params_to_function (clone);
398 gcc_assert (DECL_FUNCTION_CODE (clone) == fcode);
400 set_builtin_decl (fcode, clone, false);
402 return clone;
405 /* Return 1 if function FNDECL should be instrumented. */
407 bool
408 chkp_instrumentable_p (tree fndecl)
410 struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
411 return (!lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl))
412 && (!flag_chkp_instrument_marked_only
413 || lookup_attribute ("bnd_instrument", DECL_ATTRIBUTES (fndecl)))
414 && (!fn || !copy_forbidden (fn, fndecl)));
417 /* Return clone created for instrumentation of NODE or NULL. */
419 cgraph_node *
420 chkp_maybe_create_clone (tree fndecl)
422 cgraph_node *node = cgraph_node::get_create (fndecl);
423 cgraph_node *clone = node->instrumented_version;
425 gcc_assert (!node->instrumentation_clone);
427 if (DECL_BUILT_IN (fndecl)
428 && (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL
429 || DECL_FUNCTION_CODE (fndecl) >= BEGIN_CHKP_BUILTINS))
430 return NULL;
432 clone = node->instrumented_version;
434 /* Some instrumented builtin function calls may be optimized and
435 cgraph nodes may be removed as unreachable. Later optimizations
436 may generate new calls to removed functions and in this case
437 we have to recreate cgraph node. FUNCTION_DECL for instrumented
438 builtin still exists and should be reused in such case. */
439 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
440 && fndecl == builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl))
441 && !clone)
443 enum built_in_function fncode = DECL_FUNCTION_CODE (fndecl);
444 tree new_decl;
446 fncode = (enum built_in_function) (fncode + BEGIN_CHKP_BUILTINS + 1);
447 new_decl = builtin_decl_explicit (fncode);
449 /* We've actually already created an instrumented clone once.
450 Restore it. */
451 if (new_decl)
453 clone = cgraph_node::get (new_decl);
455 if (!clone)
457 gcc_assert (!gimple_has_body_p (fndecl));
458 clone = cgraph_node::get_create (new_decl);
459 clone->externally_visible = node->externally_visible;
460 clone->local = node->local;
461 clone->address_taken = node->address_taken;
462 clone->thunk = node->thunk;
463 clone->alias = node->alias;
464 clone->weakref = node->weakref;
465 clone->cpp_implicit_alias = node->cpp_implicit_alias;
466 clone->orig_decl = fndecl;
467 clone->instrumentation_clone = true;
470 clone->instrumented_version = node;
471 node->instrumented_version = clone;
475 if (!clone)
477 tree new_decl = chkp_build_instrumented_fndecl (fndecl);
478 struct cgraph_edge *e;
479 struct ipa_ref *ref;
480 int i;
482 clone = node->create_version_clone (new_decl, vNULL, NULL);
483 clone->externally_visible = node->externally_visible;
484 clone->local = node->local;
485 clone->address_taken = node->address_taken;
486 clone->thunk = node->thunk;
487 clone->alias = node->alias;
488 clone->weakref = node->weakref;
489 clone->cpp_implicit_alias = node->cpp_implicit_alias;
490 clone->instrumented_version = node;
491 clone->orig_decl = fndecl;
492 clone->instrumentation_clone = true;
493 node->instrumented_version = clone;
495 if (gimple_has_body_p (fndecl))
497 /* If function will not be instrumented, then it's instrumented
498 version is a thunk for the original. */
499 if (!chkp_instrumentable_p (fndecl))
501 clone->remove_callees ();
502 clone->remove_all_references ();
503 clone->thunk.thunk_p = true;
504 clone->thunk.add_pointer_bounds_args = true;
505 clone->create_edge (node, NULL, 0, CGRAPH_FREQ_BASE);
507 else
509 tree_function_versioning (fndecl, new_decl, NULL, false,
510 NULL, false, NULL, NULL);
511 clone->lowered = true;
515 /* New params are inserted after versioning because it
516 actually copies args list from the original decl. */
517 chkp_add_bounds_params_to_function (new_decl);
519 /* Remember builtin fndecl. */
520 if (DECL_BUILT_IN_CLASS (clone->decl) == BUILT_IN_NORMAL
521 && fndecl == builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl)))
523 gcc_assert (!builtin_decl_explicit (DECL_FUNCTION_CODE (clone->decl)));
524 set_builtin_decl (DECL_FUNCTION_CODE (clone->decl),
525 clone->decl, false);
528 /* Clones have the same comdat group as originals. */
529 if (node->same_comdat_group
530 || DECL_ONE_ONLY (node->decl))
531 clone->add_to_same_comdat_group (node);
533 if (gimple_has_body_p (fndecl))
534 symtab->call_cgraph_insertion_hooks (clone);
536 /* Clone all aliases. */
537 for (i = 0; node->iterate_direct_aliases (i, ref); i++)
539 struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
540 struct cgraph_node *chkp_alias
541 = chkp_maybe_create_clone (alias->decl);
542 chkp_alias->create_reference (clone, IPA_REF_ALIAS, NULL);
545 /* Clone all thunks. */
546 for (e = node->callers; e; e = e->next_caller)
547 if (e->caller->thunk.thunk_p
548 && !e->caller->thunk.add_pointer_bounds_args)
550 struct cgraph_node *thunk
551 = chkp_maybe_create_clone (e->caller->decl);
552 /* Redirect thunk clone edge to the node clone. */
553 thunk->callees->redirect_callee (clone);
556 /* For aliases and thunks we should make sure target is cloned
557 to have proper references and edges. */
558 if (node->thunk.thunk_p)
559 chkp_maybe_create_clone (node->callees->callee->decl);
560 else if (node->alias)
562 struct cgraph_node *target;
564 ref = node->ref_list.first_reference ();
565 if (ref)
566 chkp_maybe_create_clone (ref->referred->decl);
568 if (node->alias_target)
570 if (TREE_CODE (node->alias_target) == FUNCTION_DECL)
572 target = chkp_maybe_create_clone (node->alias_target);
573 clone->alias_target = target->decl;
575 else
576 clone->alias_target = node->alias_target;
580 /* Add IPA reference. It's main role is to keep instrumented
581 version reachable while original node is reachable. */
582 ref = node->create_reference (clone, IPA_REF_CHKP, NULL);
585 return clone;
588 /* Create clone for all functions to be instrumented. */
590 static unsigned int
591 chkp_versioning (void)
593 struct cgraph_node *node;
594 const char *reason;
596 bitmap_obstack_initialize (NULL);
598 FOR_EACH_DEFINED_FUNCTION (node)
600 if (!node->instrumentation_clone
601 && !node->instrumented_version
602 && !node->alias
603 && !node->thunk.thunk_p
604 && (!DECL_BUILT_IN (node->decl)
605 || (DECL_BUILT_IN_CLASS (node->decl) == BUILT_IN_NORMAL
606 && DECL_FUNCTION_CODE (node->decl) < BEGIN_CHKP_BUILTINS)))
608 if (chkp_instrumentable_p (node->decl))
609 chkp_maybe_create_clone (node->decl);
610 else if ((reason = copy_forbidden (DECL_STRUCT_FUNCTION (node->decl),
611 node->decl)))
613 if (warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wchkp,
614 "function cannot be instrumented"))
615 inform (DECL_SOURCE_LOCATION (node->decl), reason, node->decl);
620 /* Mark all aliases and thunks of functions with no instrumented
621 version as legacy function. */
622 FOR_EACH_DEFINED_FUNCTION (node)
624 if (!node->instrumentation_clone
625 && !node->instrumented_version
626 && (node->alias || node->thunk.thunk_p)
627 && !lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (node->decl)))
628 DECL_ATTRIBUTES (node->decl)
629 = tree_cons (get_identifier ("bnd_legacy"), NULL,
630 DECL_ATTRIBUTES (node->decl));
633 bitmap_obstack_release (NULL);
635 return 0;
638 /* In this pass we remove bodies of functions having
639 instrumented version. Functions with removed bodies
640 become a special kind of thunks to provide a connection
641 between calls to the original version and instrumented
642 function. */
644 static unsigned int
645 chkp_produce_thunks (bool early)
647 struct cgraph_node *node;
649 FOR_EACH_DEFINED_FUNCTION (node)
651 if (!node->instrumentation_clone
652 && node->instrumented_version
653 && gimple_has_body_p (node->decl)
654 && gimple_has_body_p (node->instrumented_version->decl)
655 && (!lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl))
656 || !early))
658 node->release_body ();
659 node->remove_callees ();
660 node->remove_all_references ();
662 node->thunk.thunk_p = true;
663 node->thunk.add_pointer_bounds_args = true;
664 node->create_edge (node->instrumented_version, NULL,
665 0, CGRAPH_FREQ_BASE);
666 node->create_reference (node->instrumented_version,
667 IPA_REF_CHKP, NULL);
671 /* Mark instrumentation clones created for aliases and thunks
672 as insttrumented so they could be removed as unreachable
673 now. */
674 if (!early)
676 FOR_EACH_DEFINED_FUNCTION (node)
678 if (node->instrumentation_clone
679 && (node->alias || node->thunk.thunk_p)
680 && !chkp_function_instrumented_p (node->decl))
681 chkp_function_mark_instrumented (node->decl);
685 return TODO_remove_functions;
688 const pass_data pass_data_ipa_chkp_versioning =
690 SIMPLE_IPA_PASS, /* type */
691 "chkp_versioning", /* name */
692 OPTGROUP_NONE, /* optinfo_flags */
693 TV_NONE, /* tv_id */
694 0, /* properties_required */
695 0, /* properties_provided */
696 0, /* properties_destroyed */
697 0, /* todo_flags_start */
698 0 /* todo_flags_finish */
701 const pass_data pass_data_ipa_chkp_early_produce_thunks =
703 SIMPLE_IPA_PASS, /* type */
704 "chkp_ecleanup", /* name */
705 OPTGROUP_NONE, /* optinfo_flags */
706 TV_NONE, /* tv_id */
707 0, /* properties_required */
708 0, /* properties_provided */
709 0, /* properties_destroyed */
710 0, /* todo_flags_start */
711 0 /* todo_flags_finish */
714 const pass_data pass_data_ipa_chkp_produce_thunks =
716 SIMPLE_IPA_PASS, /* type */
717 "chkp_cleanup", /* name */
718 OPTGROUP_NONE, /* optinfo_flags */
719 TV_NONE, /* tv_id */
720 0, /* properties_required */
721 0, /* properties_provided */
722 0, /* properties_destroyed */
723 0, /* todo_flags_start */
724 0 /* todo_flags_finish */
727 class pass_ipa_chkp_versioning : public simple_ipa_opt_pass
729 public:
730 pass_ipa_chkp_versioning (gcc::context *ctxt)
731 : simple_ipa_opt_pass (pass_data_ipa_chkp_versioning, ctxt)
734 /* opt_pass methods: */
735 virtual opt_pass * clone ()
737 return new pass_ipa_chkp_versioning (m_ctxt);
740 virtual bool gate (function *)
742 return flag_check_pointer_bounds;
745 virtual unsigned int execute (function *)
747 return chkp_versioning ();
750 }; // class pass_ipa_chkp_versioning
752 class pass_ipa_chkp_early_produce_thunks : public simple_ipa_opt_pass
754 public:
755 pass_ipa_chkp_early_produce_thunks (gcc::context *ctxt)
756 : simple_ipa_opt_pass (pass_data_ipa_chkp_early_produce_thunks, ctxt)
759 /* opt_pass methods: */
760 virtual opt_pass * clone ()
762 return new pass_ipa_chkp_early_produce_thunks (m_ctxt);
765 virtual bool gate (function *)
767 return flag_check_pointer_bounds;
770 virtual unsigned int execute (function *)
772 return chkp_produce_thunks (true);
775 }; // class pass_chkp_produce_thunks
777 class pass_ipa_chkp_produce_thunks : public simple_ipa_opt_pass
779 public:
780 pass_ipa_chkp_produce_thunks (gcc::context *ctxt)
781 : simple_ipa_opt_pass (pass_data_ipa_chkp_produce_thunks, ctxt)
784 /* opt_pass methods: */
785 virtual opt_pass * clone ()
787 return new pass_ipa_chkp_produce_thunks (m_ctxt);
790 virtual bool gate (function *)
792 return flag_check_pointer_bounds;
795 virtual unsigned int execute (function *)
797 return chkp_produce_thunks (false);
800 }; // class pass_chkp_produce_thunks
802 simple_ipa_opt_pass *
803 make_pass_ipa_chkp_versioning (gcc::context *ctxt)
805 return new pass_ipa_chkp_versioning (ctxt);
808 simple_ipa_opt_pass *
809 make_pass_ipa_chkp_early_produce_thunks (gcc::context *ctxt)
811 return new pass_ipa_chkp_early_produce_thunks (ctxt);
814 simple_ipa_opt_pass *
815 make_pass_ipa_chkp_produce_thunks (gcc::context *ctxt)
817 return new pass_ipa_chkp_produce_thunks (ctxt);