Update gcc-50 to SVN version 231263 (gcc-5-branch)
[dragonfly.git] / contrib / gcc-5.0 / gcc / ipa-chkp.c
1 /* Pointer Bounds Checker IPA passes.
2    Copyright (C) 2014-2015 Free Software Foundation, Inc.
3    Contributed by Ilya Enkovich (ilya.enkovich@intel.com)
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>.  */
20
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"
55
56 /*  Pointer Bounds Checker has two IPA passes to support code instrumentation.
57
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.
61
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.
68
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).
74
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.
80
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).
85
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.
91
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.  */
101
102 #define CHKP_BOUNDS_OF_SYMBOL_PREFIX "__chkp_bounds_of_"
103 #define CHKP_WRAPPER_SYMBOL_PREFIX "__mpx_wrapper_"
104
105 /* Return 1 calls to FNDECL should be replaced with
106    a call to wrapper function.  */
107 bool
108 chkp_wrap_function (tree fndecl)
109 {
110   if (!flag_chkp_use_wrappers)
111     return false;
112
113   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
114     {
115       switch (DECL_FUNCTION_CODE (fndecl))
116         {
117         case BUILT_IN_STRLEN:
118         case BUILT_IN_STRCPY:
119         case BUILT_IN_STRNCPY:
120         case BUILT_IN_STPCPY:
121         case BUILT_IN_STPNCPY:
122         case BUILT_IN_STRCAT:
123         case BUILT_IN_STRNCAT:
124         case BUILT_IN_MEMCPY:
125         case BUILT_IN_MEMPCPY:
126         case BUILT_IN_MEMSET:
127         case BUILT_IN_MEMMOVE:
128         case BUILT_IN_BZERO:
129         case BUILT_IN_MALLOC:
130         case BUILT_IN_CALLOC:
131         case BUILT_IN_REALLOC:
132           return 1;
133
134         default:
135           return 0;
136         }
137     }
138
139   return false;
140 }
141
142 static const char *
143 chkp_wrap_function_name (tree fndecl)
144 {
145   gcc_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
146
147   switch (DECL_FUNCTION_CODE (fndecl))
148     {
149     case BUILT_IN_STRLEN:
150       return CHKP_WRAPPER_SYMBOL_PREFIX "strlen";
151     case BUILT_IN_STRCPY:
152       return CHKP_WRAPPER_SYMBOL_PREFIX "strcpy";
153     case BUILT_IN_STRNCPY:
154       return CHKP_WRAPPER_SYMBOL_PREFIX "strncpy";
155     case BUILT_IN_STPCPY:
156       return CHKP_WRAPPER_SYMBOL_PREFIX "stpcpy";
157     case BUILT_IN_STPNCPY:
158       return CHKP_WRAPPER_SYMBOL_PREFIX "stpncpy";
159     case BUILT_IN_STRCAT:
160       return CHKP_WRAPPER_SYMBOL_PREFIX "strcat";
161     case BUILT_IN_STRNCAT:
162       return CHKP_WRAPPER_SYMBOL_PREFIX "strncat";
163     case BUILT_IN_MEMCPY:
164       return CHKP_WRAPPER_SYMBOL_PREFIX "memcpy";
165     case BUILT_IN_MEMPCPY:
166       return CHKP_WRAPPER_SYMBOL_PREFIX "mempcpy";
167     case BUILT_IN_MEMSET:
168       return CHKP_WRAPPER_SYMBOL_PREFIX "memset";
169     case BUILT_IN_MEMMOVE:
170       return CHKP_WRAPPER_SYMBOL_PREFIX "memmove";
171     case BUILT_IN_BZERO:
172       return CHKP_WRAPPER_SYMBOL_PREFIX "bzero";
173     case BUILT_IN_MALLOC:
174       return CHKP_WRAPPER_SYMBOL_PREFIX "malloc";
175     case BUILT_IN_CALLOC:
176       return CHKP_WRAPPER_SYMBOL_PREFIX "calloc";
177     case BUILT_IN_REALLOC:
178       return CHKP_WRAPPER_SYMBOL_PREFIX "realloc";
179
180     default:
181       gcc_unreachable ();
182     }
183
184   return "";
185 }
186
187 /* Build a clone of FNDECL with a modified name.  */
188
189 static tree
190 chkp_build_instrumented_fndecl (tree fndecl)
191 {
192   tree new_decl = copy_node (fndecl);
193   tree new_name;
194   std::string s;
195
196   /* called_as_built_in checks DECL_NAME to identify calls to
197      builtins.  We want instrumented calls to builtins to be
198      recognized by called_as_built_in.  Therefore use original
199      DECL_NAME for cloning with no prefixes.  */
200   s = IDENTIFIER_POINTER (DECL_NAME (fndecl));
201   s += ".chkp";
202   DECL_NAME (new_decl) = get_identifier (s.c_str ());
203
204   /* References to the original and to the instrumented version
205      should look the same in the output assembly.  And we cannot
206      use the same assembler name for the instrumented version
207      because it conflicts with decl merging algorithms in LTO.
208      Achieve the result by using transparent alias name for the
209      instrumented version.  */
210   if (chkp_wrap_function(fndecl))
211     {
212       new_name = get_identifier (chkp_wrap_function_name (fndecl));
213       DECL_VISIBILITY (new_decl) = VISIBILITY_DEFAULT;
214     }
215   else
216     {
217       s = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl));
218       s += ".chkp";
219       new_name = get_identifier (s.c_str ());
220       IDENTIFIER_TRANSPARENT_ALIAS (new_name) = 1;
221       TREE_CHAIN (new_name) = DECL_ASSEMBLER_NAME (fndecl);
222     }
223   SET_DECL_ASSEMBLER_NAME (new_decl, new_name);
224
225   /* For functions with body versioning will make a copy of arguments.
226      For functions with no body we need to do it here.  */
227   if (!gimple_has_body_p (fndecl))
228     DECL_ARGUMENTS (new_decl) = copy_list (DECL_ARGUMENTS (fndecl));
229
230   /* We are going to modify attributes list and therefore should
231      make own copy.  */
232   DECL_ATTRIBUTES (new_decl) = copy_list (DECL_ATTRIBUTES (fndecl));
233
234   /* Change builtin function code.  */
235   if (DECL_BUILT_IN (new_decl))
236     {
237       gcc_assert (DECL_BUILT_IN_CLASS (new_decl) == BUILT_IN_NORMAL);
238       gcc_assert (DECL_FUNCTION_CODE (new_decl) < BEGIN_CHKP_BUILTINS);
239       DECL_FUNCTION_CODE (new_decl)
240         = (enum built_in_function)(DECL_FUNCTION_CODE (new_decl)
241                                    + BEGIN_CHKP_BUILTINS + 1);
242     }
243
244   return new_decl;
245 }
246
247
248 /* Fix operands of attribute from ATTRS list named ATTR_NAME.
249    Integer operands are replaced with values according to
250    INDEXES map having LEN elements.  For operands out of len
251    we just add DELTA.  */
252
253 static void
254 chkp_map_attr_arg_indexes (tree attrs, const char *attr_name,
255                            unsigned *indexes, int len, int delta)
256 {
257   tree attr = lookup_attribute (attr_name, attrs);
258   tree op;
259
260   if (!attr)
261     return;
262
263   TREE_VALUE (attr) = copy_list (TREE_VALUE (attr));
264   for (op = TREE_VALUE (attr); op; op = TREE_CHAIN (op))
265     {
266       int idx;
267
268       if (TREE_CODE (TREE_VALUE (op)) != INTEGER_CST)
269         continue;
270
271       idx = TREE_INT_CST_LOW (TREE_VALUE (op));
272
273       /* If idx exceeds indexes length then we just
274          keep it at the same distance from the last
275          known arg.  */
276       if (idx > len)
277         idx += delta;
278       else
279         idx = indexes[idx - 1] + 1;
280       TREE_VALUE (op) = build_int_cst (TREE_TYPE (TREE_VALUE (op)), idx);
281     }
282 }
283
284 /* Make a copy of function type ORIG_TYPE adding pointer
285    bounds as additional arguments.  */
286
287 tree
288 chkp_copy_function_type_adding_bounds (tree orig_type)
289 {
290   tree type;
291   tree arg_type, attrs, t;
292   unsigned len = list_length (TYPE_ARG_TYPES (orig_type));
293   unsigned *indexes = XALLOCAVEC (unsigned, len);
294   unsigned idx = 0, new_idx = 0;
295
296   for (arg_type = TYPE_ARG_TYPES (orig_type);
297        arg_type;
298        arg_type = TREE_CHAIN (arg_type))
299     if (TREE_VALUE (arg_type) == void_type_node)
300       continue;
301     else if (BOUNDED_TYPE_P (TREE_VALUE (arg_type))
302              || pass_by_reference (NULL, TYPE_MODE (TREE_VALUE (arg_type)),
303                                    TREE_VALUE (arg_type), true)
304              || chkp_type_has_pointer (TREE_VALUE (arg_type)))
305       break;
306
307   /* We may use original type if there are no bounds passed.  */
308   if (!arg_type)
309     return orig_type;
310
311   type = build_distinct_type_copy (orig_type);
312   TYPE_ARG_TYPES (type) = copy_list (TYPE_ARG_TYPES (type));
313
314   for (arg_type = TYPE_ARG_TYPES (type);
315        arg_type;
316        arg_type = TREE_CHAIN (arg_type))
317     {
318       indexes[idx++] = new_idx++;
319
320       /* pass_by_reference returns 1 for void type,
321          so check for it first.  */
322       if (TREE_VALUE (arg_type) == void_type_node)
323         continue;
324       else if (BOUNDED_TYPE_P (TREE_VALUE (arg_type))
325                || pass_by_reference (NULL, TYPE_MODE (TREE_VALUE (arg_type)),
326                                      TREE_VALUE (arg_type), true))
327         {
328           tree new_type = build_tree_list (NULL_TREE,
329                                            pointer_bounds_type_node);
330           TREE_CHAIN (new_type) = TREE_CHAIN (arg_type);
331           TREE_CHAIN (arg_type) = new_type;
332
333           arg_type = TREE_CHAIN (arg_type);
334           new_idx++;
335         }
336       else if (chkp_type_has_pointer (TREE_VALUE (arg_type)))
337         {
338           bitmap slots = BITMAP_ALLOC (NULL);
339           bitmap_iterator bi;
340           unsigned bnd_no;
341
342           chkp_find_bound_slots (TREE_VALUE (arg_type), slots);
343
344           EXECUTE_IF_SET_IN_BITMAP (slots, 0, bnd_no, bi)
345             {
346               tree new_type = build_tree_list (NULL_TREE,
347                                                pointer_bounds_type_node);
348               TREE_CHAIN (new_type) = TREE_CHAIN (arg_type);
349               TREE_CHAIN (arg_type) = new_type;
350
351               arg_type = TREE_CHAIN (arg_type);
352               new_idx++;
353             }
354           BITMAP_FREE (slots);
355         }
356     }
357
358   /* If function type has attribute with arg indexes then
359      we have to copy it fixing attribute ops.  Map for
360      fixing is in indexes array.  */
361   attrs = TYPE_ATTRIBUTES (type);
362   if (lookup_attribute ("nonnull", attrs)
363       || lookup_attribute ("format", attrs)
364       || lookup_attribute ("format_arg", attrs))
365     {
366       int delta = new_idx - len;
367       attrs = copy_list (TYPE_ATTRIBUTES (type));
368       chkp_map_attr_arg_indexes (attrs, "nonnull", indexes, len, delta);
369       chkp_map_attr_arg_indexes (attrs, "format", indexes, len, delta);
370       chkp_map_attr_arg_indexes (attrs, "format_arg", indexes, len, delta);
371       TYPE_ATTRIBUTES (type) = attrs;
372     }
373
374   t = TYPE_MAIN_VARIANT (orig_type);
375   if (orig_type != t)
376     {
377       TYPE_MAIN_VARIANT (type) = t;
378       TYPE_NEXT_VARIANT (type) = TYPE_NEXT_VARIANT (t);
379       TYPE_NEXT_VARIANT (t) = type;
380     }
381   else
382     {
383       TYPE_MAIN_VARIANT (type) = type;
384       TYPE_NEXT_VARIANT (type) = NULL;
385     }
386
387
388   return type;
389 }
390
391 /* For given function FNDECL add bounds arguments to arguments
392    list.  */
393
394 static void
395 chkp_add_bounds_params_to_function (tree fndecl)
396 {
397   tree arg;
398
399   for (arg = DECL_ARGUMENTS (fndecl); arg; arg = DECL_CHAIN (arg))
400     if (BOUNDED_P (arg))
401       {
402         std::string new_name = CHKP_BOUNDS_OF_SYMBOL_PREFIX;
403         tree new_arg;
404
405         if (DECL_NAME (arg))
406           new_name += IDENTIFIER_POINTER (DECL_NAME (arg));
407         else
408           {
409             char uid[25];
410             snprintf (uid, 25, "D.%u", DECL_UID (arg));
411             new_name += uid;
412           }
413
414         new_arg = build_decl (DECL_SOURCE_LOCATION (arg), PARM_DECL,
415                               get_identifier (new_name.c_str ()),
416                               pointer_bounds_type_node);
417         DECL_ARG_TYPE (new_arg) = pointer_bounds_type_node;
418         DECL_CONTEXT (new_arg) = DECL_CONTEXT (arg);
419         DECL_ARTIFICIAL (new_arg) = 1;
420         DECL_CHAIN (new_arg) = DECL_CHAIN (arg);
421         DECL_CHAIN (arg) = new_arg;
422
423         arg = DECL_CHAIN (arg);
424
425       }
426     else if (chkp_type_has_pointer (TREE_TYPE (arg)))
427       {
428         tree orig_arg = arg;
429         bitmap slots = BITMAP_ALLOC (NULL);
430         bitmap_iterator bi;
431         unsigned bnd_no;
432
433         chkp_find_bound_slots (TREE_TYPE (arg), slots);
434
435         EXECUTE_IF_SET_IN_BITMAP (slots, 0, bnd_no, bi)
436           {
437             std::string new_name = CHKP_BOUNDS_OF_SYMBOL_PREFIX;
438             tree new_arg;
439             char offs[25];
440
441             if (DECL_NAME (orig_arg))
442               new_name += IDENTIFIER_POINTER (DECL_NAME (orig_arg));
443             else
444               {
445                 snprintf (offs, 25, "D.%u", DECL_UID (arg));
446                 new_name += offs;
447               }
448             snprintf (offs, 25, "__%u", bnd_no * POINTER_SIZE / BITS_PER_UNIT);
449
450             new_arg = build_decl (DECL_SOURCE_LOCATION (orig_arg),
451                                   PARM_DECL,
452                                   get_identifier (new_name.c_str ()),
453                                   pointer_bounds_type_node);
454             DECL_ARG_TYPE (new_arg) = pointer_bounds_type_node;
455             DECL_CONTEXT (new_arg) = DECL_CONTEXT (orig_arg);
456             DECL_ARTIFICIAL (new_arg) = 1;
457             DECL_CHAIN (new_arg) = DECL_CHAIN (arg);
458             DECL_CHAIN (arg) = new_arg;
459
460             arg = DECL_CHAIN (arg);
461           }
462         BITMAP_FREE (slots);
463       }
464
465   TREE_TYPE (fndecl) =
466     chkp_copy_function_type_adding_bounds (TREE_TYPE (fndecl));
467 }
468
469 /* Return an instrumentation clone for builtin function
470    FNDECL.  Create one if needed.  */
471
472 tree
473 chkp_maybe_clone_builtin_fndecl (tree fndecl)
474 {
475   tree clone;
476   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
477
478   gcc_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
479               && fcode < BEGIN_CHKP_BUILTINS);
480
481   fcode = (enum built_in_function) (fcode + BEGIN_CHKP_BUILTINS + 1);
482   clone = builtin_decl_explicit (fcode);
483   if (clone)
484     return clone;
485
486   clone = chkp_build_instrumented_fndecl (fndecl);
487   chkp_add_bounds_params_to_function (clone);
488
489   gcc_assert (DECL_FUNCTION_CODE (clone) == fcode);
490
491   set_builtin_decl (fcode, clone, false);
492
493   return clone;
494 }
495
496 /* Return 1 if function FNDECL should be instrumented.  */
497
498 bool
499 chkp_instrumentable_p (tree fndecl)
500 {
501   struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
502   return (!lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl))
503           && (!flag_chkp_instrument_marked_only
504               || lookup_attribute ("bnd_instrument", DECL_ATTRIBUTES (fndecl)))
505           && (!fn || !copy_forbidden (fn, fndecl)));
506 }
507
508 /* Return clone created for instrumentation of NODE or NULL.  */
509
510 cgraph_node *
511 chkp_maybe_create_clone (tree fndecl)
512 {
513   cgraph_node *node = cgraph_node::get_create (fndecl);
514   cgraph_node *clone = node->instrumented_version;
515
516   gcc_assert (!node->instrumentation_clone);
517
518   if (DECL_BUILT_IN (fndecl)
519       && (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL
520           || DECL_FUNCTION_CODE (fndecl) >= BEGIN_CHKP_BUILTINS))
521     return NULL;
522
523   clone = node->instrumented_version;
524
525   /* Some instrumented builtin function calls may be optimized and
526      cgraph nodes may be removed as unreachable.  Later optimizations
527      may generate new calls to removed functions and in this case
528      we have to recreate cgraph node.  FUNCTION_DECL for instrumented
529      builtin still exists and should be reused in such case.  */
530   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
531       && fndecl == builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl))
532       && !clone)
533     {
534       enum built_in_function fncode = DECL_FUNCTION_CODE (fndecl);
535       tree new_decl;
536
537       fncode = (enum built_in_function) (fncode + BEGIN_CHKP_BUILTINS + 1);
538       new_decl = builtin_decl_explicit (fncode);
539
540       /* We've actually already created an instrumented clone once.
541          Restore it.  */
542       if (new_decl)
543         {
544           clone = cgraph_node::get (new_decl);
545
546           if (!clone)
547             {
548               gcc_assert (!gimple_has_body_p (fndecl));
549               clone = cgraph_node::get_create (new_decl);
550               clone->externally_visible = node->externally_visible;
551               clone->local = node->local;
552               clone->address_taken = node->address_taken;
553               clone->thunk = node->thunk;
554               clone->alias = node->alias;
555               clone->weakref = node->weakref;
556               clone->cpp_implicit_alias = node->cpp_implicit_alias;
557               clone->orig_decl = fndecl;
558               clone->instrumentation_clone = true;
559             }
560
561           clone->instrumented_version = node;
562           node->instrumented_version = clone;
563         }
564     }
565
566   if (!clone)
567     {
568       tree new_decl = chkp_build_instrumented_fndecl (fndecl);
569       struct cgraph_edge *e;
570       struct ipa_ref *ref;
571       int i;
572
573       clone = node->create_version_clone (new_decl, vNULL, NULL);
574       clone->externally_visible = node->externally_visible;
575       clone->local = node->local;
576       clone->address_taken = node->address_taken;
577       clone->thunk = node->thunk;
578       clone->alias = node->alias;
579       clone->weakref = node->weakref;
580       clone->cpp_implicit_alias = node->cpp_implicit_alias;
581       clone->instrumented_version = node;
582       clone->orig_decl = fndecl;
583       clone->instrumentation_clone = true;
584       node->instrumented_version = clone;
585
586       if (gimple_has_body_p (fndecl))
587         {
588           gcc_assert (chkp_instrumentable_p (fndecl));
589           tree_function_versioning (fndecl, new_decl, NULL, false,
590                                     NULL, false, NULL, NULL);
591           clone->lowered = true;
592         }
593
594       /* New params are inserted after versioning because it
595          actually copies args list from the original decl.  */
596       chkp_add_bounds_params_to_function (new_decl);
597
598       /* Remember builtin fndecl.  */
599       if (DECL_BUILT_IN_CLASS (clone->decl) == BUILT_IN_NORMAL
600           && fndecl == builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl)))
601         {
602           gcc_assert (!builtin_decl_explicit (DECL_FUNCTION_CODE (clone->decl)));
603           set_builtin_decl (DECL_FUNCTION_CODE (clone->decl),
604                             clone->decl, false);
605         }
606
607       /* Clones have the same comdat group as originals.  */
608       if (node->same_comdat_group
609           || (DECL_ONE_ONLY (node->decl)
610               && !DECL_EXTERNAL (node->decl)))
611         clone->add_to_same_comdat_group (node);
612
613       if (gimple_has_body_p (fndecl))
614         symtab->call_cgraph_insertion_hooks (clone);
615
616       /* Clone all aliases.  */
617       for (i = 0; node->iterate_direct_aliases (i, ref); i++)
618         chkp_maybe_create_clone (ref->referring->decl);
619
620       /* Clone all thunks.  */
621       for (e = node->callers; e; e = e->next_caller)
622         if (e->caller->thunk.thunk_p
623             && !e->caller->thunk.add_pointer_bounds_args
624             && !e->caller->instrumentation_clone)
625           {
626             struct cgraph_node *thunk
627               = chkp_maybe_create_clone (e->caller->decl);
628             /* Redirect thunk clone edge to the node clone.  */
629             thunk->callees->redirect_callee (clone);
630           }
631
632       /* For aliases and thunks we should make sure target is cloned
633          to have proper references and edges.  */
634       if (node->thunk.thunk_p)
635         chkp_maybe_create_clone (node->callees->callee->decl);
636       else if (node->alias)
637         {
638           struct cgraph_node *target;
639
640           ref = node->ref_list.first_reference ();
641           if (ref)
642             {
643               target = chkp_maybe_create_clone (ref->referred->decl);
644               clone->create_reference (target, IPA_REF_ALIAS);
645             }
646
647           if (node->alias_target)
648             {
649               if (TREE_CODE (node->alias_target) == FUNCTION_DECL)
650                 {
651                   target = chkp_maybe_create_clone (node->alias_target);
652                   clone->alias_target = target->decl;
653                 }
654               else
655                 clone->alias_target = node->alias_target;
656             }
657         }
658
659       /* Add IPA reference.  It's main role is to keep instrumented
660          version reachable while original node is reachable.  */
661       ref = node->create_reference (clone, IPA_REF_CHKP, NULL);
662     }
663
664   return clone;
665 }
666
667 /* Create clone for all functions to be instrumented.  */
668
669 static unsigned int
670 chkp_versioning (void)
671 {
672   struct cgraph_node *node;
673   const char *reason;
674
675   bitmap_obstack_initialize (NULL);
676
677   FOR_EACH_DEFINED_FUNCTION (node)
678     {
679       if (!node->instrumentation_clone
680           && !node->instrumented_version
681           && !node->alias
682           && !node->thunk.thunk_p
683           && (!DECL_BUILT_IN (node->decl)
684               || (DECL_BUILT_IN_CLASS (node->decl) == BUILT_IN_NORMAL
685                   && DECL_FUNCTION_CODE (node->decl) < BEGIN_CHKP_BUILTINS)))
686         {
687           if (chkp_instrumentable_p (node->decl))
688             chkp_maybe_create_clone (node->decl);
689           else if ((reason = copy_forbidden (DECL_STRUCT_FUNCTION (node->decl),
690                                              node->decl)))
691             {
692               if (warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wchkp,
693                               "function cannot be instrumented"))
694                 inform (DECL_SOURCE_LOCATION (node->decl), reason, node->decl);
695             }
696         }
697     }
698
699   /* Mark all aliases and thunks of functions with no instrumented
700      version as legacy function.  */
701   FOR_EACH_DEFINED_FUNCTION (node)
702     {
703       if (!node->instrumentation_clone
704           && !node->instrumented_version
705           && (node->alias || node->thunk.thunk_p)
706           && !lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (node->decl)))
707         DECL_ATTRIBUTES (node->decl)
708           = tree_cons (get_identifier ("bnd_legacy"), NULL,
709                        DECL_ATTRIBUTES (node->decl));
710     }
711
712   bitmap_obstack_release (NULL);
713
714   return 0;
715 }
716
717 /* In this pass we remove bodies of functions having
718    instrumented version.  Functions with removed bodies
719    become a special kind of thunks to provide a connection
720    between calls to the original version and instrumented
721    function.  */
722
723 static unsigned int
724 chkp_produce_thunks (bool early)
725 {
726   struct cgraph_node *node;
727
728   FOR_EACH_DEFINED_FUNCTION (node)
729     {
730       if (!node->instrumentation_clone
731           && node->instrumented_version
732           && gimple_has_body_p (node->decl)
733           && gimple_has_body_p (node->instrumented_version->decl)
734           && (!lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl))
735               || !early))
736         {
737           node->release_body ();
738           node->remove_callees ();
739           node->remove_all_references ();
740
741           node->thunk.thunk_p = true;
742           node->thunk.add_pointer_bounds_args = true;
743           node->create_edge (node->instrumented_version, NULL,
744                              0, CGRAPH_FREQ_BASE);
745           node->create_reference (node->instrumented_version,
746                                IPA_REF_CHKP, NULL);
747           /* Thunk shouldn't be a cdtor.  */
748           DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
749           DECL_STATIC_DESTRUCTOR (node->decl) = 0;
750         }
751     }
752
753   /* Mark instrumentation clones created for aliases and thunks
754      as insttrumented so they could be removed as unreachable
755      now.  */
756   if (!early)
757     {
758       FOR_EACH_DEFINED_FUNCTION (node)
759       {
760         if (node->instrumentation_clone
761             && (node->alias || node->thunk.thunk_p)
762             && !chkp_function_instrumented_p (node->decl))
763           chkp_function_mark_instrumented (node->decl);
764       }
765     }
766
767   return TODO_remove_functions;
768 }
769
770 const pass_data pass_data_ipa_chkp_versioning =
771 {
772   SIMPLE_IPA_PASS, /* type */
773   "chkp_versioning", /* name */
774   OPTGROUP_NONE, /* optinfo_flags */
775   TV_NONE, /* tv_id */
776   0, /* properties_required */
777   0, /* properties_provided */
778   0, /* properties_destroyed */
779   0, /* todo_flags_start */
780   0 /* todo_flags_finish */
781 };
782
783 const pass_data pass_data_ipa_chkp_early_produce_thunks =
784 {
785   SIMPLE_IPA_PASS, /* type */
786   "chkp_ecleanup", /* name */
787   OPTGROUP_NONE, /* optinfo_flags */
788   TV_NONE, /* tv_id */
789   0, /* properties_required */
790   0, /* properties_provided */
791   0, /* properties_destroyed */
792   0, /* todo_flags_start */
793   0 /* todo_flags_finish */
794 };
795
796 const pass_data pass_data_ipa_chkp_produce_thunks =
797 {
798   SIMPLE_IPA_PASS, /* type */
799   "chkp_cleanup", /* name */
800   OPTGROUP_NONE, /* optinfo_flags */
801   TV_NONE, /* tv_id */
802   0, /* properties_required */
803   0, /* properties_provided */
804   0, /* properties_destroyed */
805   0, /* todo_flags_start */
806   0 /* todo_flags_finish */
807 };
808
809 class pass_ipa_chkp_versioning : public simple_ipa_opt_pass
810 {
811 public:
812   pass_ipa_chkp_versioning (gcc::context *ctxt)
813     : simple_ipa_opt_pass (pass_data_ipa_chkp_versioning, ctxt)
814   {}
815
816   /* opt_pass methods: */
817   virtual opt_pass * clone ()
818     {
819       return new pass_ipa_chkp_versioning (m_ctxt);
820     }
821
822   virtual bool gate (function *)
823     {
824       return flag_check_pointer_bounds;
825     }
826
827   virtual unsigned int execute (function *)
828     {
829       return chkp_versioning ();
830     }
831
832 }; // class pass_ipa_chkp_versioning
833
834 class pass_ipa_chkp_early_produce_thunks : public simple_ipa_opt_pass
835 {
836 public:
837   pass_ipa_chkp_early_produce_thunks (gcc::context *ctxt)
838     : simple_ipa_opt_pass (pass_data_ipa_chkp_early_produce_thunks, ctxt)
839   {}
840
841   /* opt_pass methods: */
842   virtual opt_pass * clone ()
843     {
844       return new pass_ipa_chkp_early_produce_thunks (m_ctxt);
845     }
846
847   virtual bool gate (function *)
848     {
849       return flag_check_pointer_bounds;
850     }
851
852   virtual unsigned int execute (function *)
853     {
854       return chkp_produce_thunks (true);
855     }
856
857 }; // class pass_chkp_produce_thunks
858
859 class pass_ipa_chkp_produce_thunks : public simple_ipa_opt_pass
860 {
861 public:
862   pass_ipa_chkp_produce_thunks (gcc::context *ctxt)
863     : simple_ipa_opt_pass (pass_data_ipa_chkp_produce_thunks, ctxt)
864   {}
865
866   /* opt_pass methods: */
867   virtual opt_pass * clone ()
868     {
869       return new pass_ipa_chkp_produce_thunks (m_ctxt);
870     }
871
872   virtual bool gate (function *)
873     {
874       return flag_check_pointer_bounds;
875     }
876
877   virtual unsigned int execute (function *)
878     {
879       return chkp_produce_thunks (false);
880     }
881
882 }; // class pass_chkp_produce_thunks
883
884 simple_ipa_opt_pass *
885 make_pass_ipa_chkp_versioning (gcc::context *ctxt)
886 {
887   return new pass_ipa_chkp_versioning (ctxt);
888 }
889
890 simple_ipa_opt_pass *
891 make_pass_ipa_chkp_early_produce_thunks (gcc::context *ctxt)
892 {
893   return new pass_ipa_chkp_early_produce_thunks (ctxt);
894 }
895
896 simple_ipa_opt_pass *
897 make_pass_ipa_chkp_produce_thunks (gcc::context *ctxt)
898 {
899   return new pass_ipa_chkp_produce_thunks (ctxt);
900 }