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
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
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/>. */
23 #include "coretypes.h"
27 #include "double-int.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
37 #include "tree-pass.h"
38 #include "stringpool.h"
40 #include "gimple-expr.h"
42 #include "hard-reg-set.h"
45 #include "tree-ssa-alias.h"
47 #include "basic-block.h"
50 #include "lto-streamer.h"
52 #include "tree-chkp.h"
53 #include "tree-inline.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
102 #define CHKP_BOUNDS_OF_SYMBOL_PREFIX "__chkp_bounds_of_"
104 /* Build a clone of FNDECL with a modified name. */
107 chkp_build_instrumented_fndecl (tree fndecl
)
109 tree new_decl
= copy_node (fndecl
);
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
));
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
));
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
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);
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. */
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
);
172 TREE_VALUE (attr
) = copy_list (TREE_VALUE (attr
));
173 for (op
= TREE_VALUE (attr
); op
; op
= TREE_CHAIN (op
))
177 if (TREE_CODE (TREE_VALUE (op
)) != INTEGER_CST
)
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
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. */
197 chkp_copy_function_type_adding_bounds (tree orig_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
);
207 arg_type
= TREE_CHAIN (arg_type
))
208 if (TREE_VALUE (arg_type
) == void_type_node
)
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
)))
216 /* We may use original type if there are no bounds passed. */
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
);
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
)
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
);
245 else if (chkp_type_has_pointer (TREE_VALUE (arg_type
)))
247 bitmap slots
= BITMAP_ALLOC (NULL
);
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
);
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
);
286 TYPE_MAIN_VARIANT (type
) = t
;
287 TYPE_NEXT_VARIANT (type
) = TYPE_NEXT_VARIANT (t
);
288 TYPE_NEXT_VARIANT (t
) = type
;
292 TYPE_MAIN_VARIANT (type
) = type
;
293 TYPE_NEXT_VARIANT (type
) = NULL
;
300 /* For given function FNDECL add bounds arguments to arguments
304 chkp_add_bounds_params_to_function (tree fndecl
)
308 for (arg
= DECL_ARGUMENTS (fndecl
); arg
; arg
= DECL_CHAIN (arg
))
311 std::string new_name
= CHKP_BOUNDS_OF_SYMBOL_PREFIX
;
315 new_name
+= IDENTIFIER_POINTER (DECL_NAME (arg
));
319 snprintf (uid
, 25, "D.%u", DECL_UID (arg
));
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
)))
338 bitmap slots
= BITMAP_ALLOC (NULL
);
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
;
350 if (DECL_NAME (orig_arg
))
351 new_name
+= IDENTIFIER_POINTER (DECL_NAME (orig_arg
));
354 snprintf (offs
, 25, "D.%u", DECL_UID (arg
));
357 snprintf (offs
, 25, "__%u", bnd_no
* POINTER_SIZE
/ BITS_PER_UNIT
);
359 new_arg
= build_decl (DECL_SOURCE_LOCATION (orig_arg
),
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
);
375 chkp_copy_function_type_adding_bounds (TREE_TYPE (fndecl
));
378 /* Return an instrumentation clone for builtin function
379 FNDECL. Create one if needed. */
382 chkp_maybe_clone_builtin_fndecl (tree fndecl
)
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
);
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);
405 /* Return 1 if function FNDECL should be instrumented. */
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. */
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
))
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
))
443 enum built_in_function fncode
= DECL_FUNCTION_CODE (fndecl
);
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.
453 clone
= cgraph_node::get (new_decl
);
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
;
477 tree new_decl
= chkp_build_instrumented_fndecl (fndecl
);
478 struct cgraph_edge
*e
;
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
);
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
),
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_referring (i
, ref
); i
++)
538 if (ref
->use
== IPA_REF_ALIAS
)
540 struct cgraph_node
*alias
= dyn_cast
<cgraph_node
*> (ref
->referring
);
541 struct cgraph_node
*chkp_alias
542 = chkp_maybe_create_clone (alias
->decl
);
543 chkp_alias
->create_reference (clone
, IPA_REF_ALIAS
, NULL
);
546 /* Clone all thunks. */
547 for (e
= node
->callers
; e
; e
= e
->next_caller
)
548 if (e
->caller
->thunk
.thunk_p
549 && !e
->caller
->thunk
.add_pointer_bounds_args
)
551 struct cgraph_node
*thunk
552 = chkp_maybe_create_clone (e
->caller
->decl
);
553 /* Redirect thunk clone edge to the node clone. */
554 thunk
->callees
->redirect_callee (clone
);
557 /* For aliases and thunks we should make sure target is cloned
558 to have proper references and edges. */
559 if (node
->thunk
.thunk_p
)
560 chkp_maybe_create_clone (node
->callees
->callee
->decl
);
561 else if (node
->alias
)
563 struct cgraph_node
*target
;
565 ref
= node
->ref_list
.first_reference ();
567 chkp_maybe_create_clone (ref
->referred
->decl
);
569 if (node
->alias_target
)
571 if (TREE_CODE (node
->alias_target
) == FUNCTION_DECL
)
573 target
= chkp_maybe_create_clone (node
->alias_target
);
574 clone
->alias_target
= target
->decl
;
577 clone
->alias_target
= node
->alias_target
;
581 /* Add IPA reference. It's main role is to keep instrumented
582 version reachable while original node is reachable. */
583 ref
= node
->create_reference (clone
, IPA_REF_CHKP
, NULL
);
589 /* Create clone for all functions to be instrumented. */
592 chkp_versioning (void)
594 struct cgraph_node
*node
;
597 bitmap_obstack_initialize (NULL
);
599 FOR_EACH_DEFINED_FUNCTION (node
)
601 if (!node
->instrumentation_clone
602 && !node
->instrumented_version
604 && !node
->thunk
.thunk_p
605 && (!DECL_BUILT_IN (node
->decl
)
606 || (DECL_BUILT_IN_CLASS (node
->decl
) == BUILT_IN_NORMAL
607 && DECL_FUNCTION_CODE (node
->decl
) < BEGIN_CHKP_BUILTINS
)))
609 if (chkp_instrumentable_p (node
->decl
))
610 chkp_maybe_create_clone (node
->decl
);
611 else if ((reason
= copy_forbidden (DECL_STRUCT_FUNCTION (node
->decl
),
614 if (warning_at (DECL_SOURCE_LOCATION (node
->decl
), OPT_Wchkp
,
615 "function cannot be instrumented"))
616 inform (DECL_SOURCE_LOCATION (node
->decl
), reason
, node
->decl
);
621 /* Mark all aliases and thunks of functions with no instrumented
622 version as legacy function. */
623 FOR_EACH_DEFINED_FUNCTION (node
)
625 if (!node
->instrumentation_clone
626 && !node
->instrumented_version
627 && (node
->alias
|| node
->thunk
.thunk_p
)
628 && !lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (node
->decl
)))
629 DECL_ATTRIBUTES (node
->decl
)
630 = tree_cons (get_identifier ("bnd_legacy"), NULL
,
631 DECL_ATTRIBUTES (node
->decl
));
634 bitmap_obstack_release (NULL
);
639 /* In this pass we remove bodies of functions having
640 instrumented version. Functions with removed bodies
641 become a special kind of thunks to provide a connection
642 between calls to the original version and instrumented
646 chkp_produce_thunks (void)
648 struct cgraph_node
*node
;
650 FOR_EACH_DEFINED_FUNCTION (node
)
652 if (!node
->instrumentation_clone
653 && node
->instrumented_version
654 && gimple_has_body_p (node
->decl
)
655 && gimple_has_body_p (node
->instrumented_version
->decl
))
657 node
->release_body ();
658 node
->remove_callees ();
659 node
->remove_all_references ();
661 node
->thunk
.thunk_p
= true;
662 node
->thunk
.add_pointer_bounds_args
= true;
663 node
->create_edge (node
->instrumented_version
, NULL
,
664 0, CGRAPH_FREQ_BASE
);
665 node
->create_reference (node
->instrumented_version
,
670 /* Mark instrumentation clones created for aliases and thunks
671 as insttrumented so they could be removed as unreachable
673 FOR_EACH_DEFINED_FUNCTION (node
)
675 if (node
->instrumentation_clone
676 && (node
->alias
|| node
->thunk
.thunk_p
)
677 && !chkp_function_instrumented_p (node
->decl
))
678 chkp_function_mark_instrumented (node
->decl
);
681 return TODO_remove_functions
;
684 const pass_data pass_data_ipa_chkp_versioning
=
686 SIMPLE_IPA_PASS
, /* type */
687 "chkp_versioning", /* name */
688 OPTGROUP_NONE
, /* optinfo_flags */
690 0, /* properties_required */
691 0, /* properties_provided */
692 0, /* properties_destroyed */
693 0, /* todo_flags_start */
694 0 /* todo_flags_finish */
697 const pass_data pass_data_ipa_chkp_produce_thunks
=
699 SIMPLE_IPA_PASS
, /* type */
700 "chkp_cleanup", /* name */
701 OPTGROUP_NONE
, /* optinfo_flags */
703 0, /* properties_required */
704 0, /* properties_provided */
705 0, /* properties_destroyed */
706 0, /* todo_flags_start */
707 0 /* todo_flags_finish */
710 class pass_ipa_chkp_versioning
: public simple_ipa_opt_pass
713 pass_ipa_chkp_versioning (gcc::context
*ctxt
)
714 : simple_ipa_opt_pass (pass_data_ipa_chkp_versioning
, ctxt
)
717 /* opt_pass methods: */
718 virtual opt_pass
* clone ()
720 return new pass_ipa_chkp_versioning (m_ctxt
);
723 virtual bool gate (function
*)
725 return flag_check_pointer_bounds
;
728 virtual unsigned int execute (function
*)
730 return chkp_versioning ();
733 }; // class pass_ipa_chkp_versioning
735 class pass_ipa_chkp_produce_thunks
: public simple_ipa_opt_pass
738 pass_ipa_chkp_produce_thunks (gcc::context
*ctxt
)
739 : simple_ipa_opt_pass (pass_data_ipa_chkp_produce_thunks
, ctxt
)
742 /* opt_pass methods: */
743 virtual opt_pass
* clone ()
745 return new pass_ipa_chkp_produce_thunks (m_ctxt
);
748 virtual bool gate (function
*)
750 return flag_check_pointer_bounds
;
753 virtual unsigned int execute (function
*)
755 return chkp_produce_thunks ();
758 }; // class pass_chkp_produce_thunks
760 simple_ipa_opt_pass
*
761 make_pass_ipa_chkp_versioning (gcc::context
*ctxt
)
763 return new pass_ipa_chkp_versioning (ctxt
);
766 simple_ipa_opt_pass
*
767 make_pass_ipa_chkp_produce_thunks (gcc::context
*ctxt
)
769 return new pass_ipa_chkp_produce_thunks (ctxt
);