[Ada] Argument_String_To_List creates empty items from whitespace
[gcc.git] / gcc / symbol-summary.h
1 /* Callgraph summary data structure.
2 Copyright (C) 2014-2018 Free Software Foundation, Inc.
3 Contributed by Martin Liska
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 #ifndef GCC_SYMBOL_SUMMARY_H
22 #define GCC_SYMBOL_SUMMARY_H
23
24 /* We want to pass just pointer types as argument for function_summary
25 template class. */
26
27 template <class T>
28 class function_summary
29 {
30 private:
31 function_summary();
32 };
33
34 /* Function summary is a helper class that is used to associate a data structure
35 related to a callgraph node. Typical usage can be seen in IPA passes which
36 create a temporary pass-related structures. The summary class registers
37 hooks that are triggered when a new node is inserted, duplicated and deleted.
38 A user of a summary class can ovewrite virtual methods than are triggered by
39 the summary if such hook is triggered. Apart from a callgraph node, the user
40 is given a data structure tied to the node.
41
42 The function summary class can work both with a heap-allocated memory and
43 a memory gained by garbage collected memory. */
44
45 template <class T>
46 class GTY((user)) function_summary <T *>
47 {
48 public:
49 /* Default construction takes SYMTAB as an argument. */
50 function_summary (symbol_table *symtab, bool ggc = false);
51
52 /* Destructor. */
53 virtual ~function_summary ()
54 {
55 release ();
56 }
57
58 /* Destruction method that can be called for GGT purpose. */
59 void release ();
60
61 /* Traverses all summarys with a function F called with
62 ARG as argument. */
63 template<typename Arg, bool (*f)(const T &, Arg)>
64 void traverse (Arg a) const
65 {
66 m_map.traverse <f> (a);
67 }
68
69 /* Basic implementation of insert operation. */
70 virtual void insert (cgraph_node *, T *) {}
71
72 /* Basic implementation of removal operation. */
73 virtual void remove (cgraph_node *, T *) {}
74
75 /* Basic implementation of duplication operation. */
76 virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) {}
77
78 /* Allocates new data that are stored within map. */
79 T* allocate_new ()
80 {
81 /* Call gcc_internal_because we do not want to call finalizer for
82 a type T. We call dtor explicitly. */
83 return m_ggc ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ;
84 }
85
86 /* Release an item that is stored within map. */
87 void release (T *item);
88
89 /* Getter for summary callgraph node pointer. If a summary for a node
90 does not exist it will be created. */
91 T* get_create (cgraph_node *node)
92 {
93 bool existed;
94 T **v = &m_map.get_or_insert (node->get_uid (), &existed);
95 if (!existed)
96 *v = allocate_new ();
97
98 return *v;
99 }
100
101 /* Getter for summary callgraph node pointer. */
102 T* get (cgraph_node *node) ATTRIBUTE_PURE
103 {
104 T **v = m_map.get (node->get_uid ());
105 return v == NULL ? NULL : *v;
106 }
107
108 /* Remove node from summary. */
109 void remove (cgraph_node *node)
110 {
111 int uid = node->get_uid ();
112 T **v = m_map.get (uid);
113 if (v)
114 {
115 m_map.remove (uid);
116 release (*v);
117 }
118 }
119
120 /* Return number of elements handled by data structure. */
121 size_t elements ()
122 {
123 return m_map.elements ();
124 }
125
126 /* Return true if a summary for the given NODE already exists. */
127 bool exists (cgraph_node *node)
128 {
129 return m_map.get (node->get_uid ()) != NULL;
130 }
131
132 /* Enable insertion hook invocation. */
133 void enable_insertion_hook ()
134 {
135 m_insertion_enabled = true;
136 }
137
138 /* Enable insertion hook invocation. */
139 void disable_insertion_hook ()
140 {
141 m_insertion_enabled = false;
142 }
143
144 /* Symbol insertion hook that is registered to symbol table. */
145 static void symtab_insertion (cgraph_node *node, void *data);
146
147 /* Symbol removal hook that is registered to symbol table. */
148 static void symtab_removal (cgraph_node *node, void *data);
149
150 /* Symbol duplication hook that is registered to symbol table. */
151 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
152 void *data);
153
154 protected:
155 /* Indication if we use ggc summary. */
156 bool m_ggc;
157
158 private:
159 typedef int_hash <int, 0, -1> map_hash;
160
161 /* Indicates if insertion hook is enabled. */
162 bool m_insertion_enabled;
163 /* Indicates if the summary is released. */
164 bool m_released;
165 /* Main summary store, where summary ID is used as key. */
166 hash_map <map_hash, T *> m_map;
167 /* Internal summary insertion hook pointer. */
168 cgraph_node_hook_list *m_symtab_insertion_hook;
169 /* Internal summary removal hook pointer. */
170 cgraph_node_hook_list *m_symtab_removal_hook;
171 /* Internal summary duplication hook pointer. */
172 cgraph_2node_hook_list *m_symtab_duplication_hook;
173 /* Symbol table the summary is registered to. */
174 symbol_table *m_symtab;
175
176 template <typename U> friend void gt_ggc_mx (function_summary <U *> * const &);
177 template <typename U> friend void gt_pch_nx (function_summary <U *> * const &);
178 template <typename U> friend void gt_pch_nx (function_summary <U *> * const &,
179 gt_pointer_operator, void *);
180 };
181
182 template <typename T>
183 function_summary<T *>::function_summary (symbol_table *symtab, bool ggc):
184 m_ggc (ggc), m_insertion_enabled (true), m_released (false), m_map (13, ggc),
185 m_symtab (symtab)
186 {
187 m_symtab_insertion_hook
188 = symtab->add_cgraph_insertion_hook (function_summary::symtab_insertion,
189 this);
190
191 m_symtab_removal_hook
192 = symtab->add_cgraph_removal_hook (function_summary::symtab_removal, this);
193 m_symtab_duplication_hook
194 = symtab->add_cgraph_duplication_hook (function_summary::symtab_duplication,
195 this);
196 }
197
198 template <typename T>
199 void
200 function_summary<T *>::release ()
201 {
202 if (m_released)
203 return;
204
205 m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
206 m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
207 m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
208
209 /* Release all summaries. */
210 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
211 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
212 release ((*it).second);
213
214 m_released = true;
215 }
216
217 template <typename T>
218 void
219 function_summary<T *>::release (T *item)
220 {
221 if (m_ggc)
222 {
223 item->~T ();
224 ggc_free (item);
225 }
226 else
227 delete item;
228 }
229
230 template <typename T>
231 void
232 function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
233 {
234 gcc_checking_assert (node->get_uid ());
235 function_summary *summary = (function_summary <T *> *) (data);
236
237 if (summary->m_insertion_enabled)
238 summary->insert (node, summary->get_create (node));
239 }
240
241 template <typename T>
242 void
243 function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
244 {
245 gcc_checking_assert (node->get_uid ());
246 function_summary *summary = (function_summary <T *> *) (data);
247
248 int uid = node->get_uid ();
249 T **v = summary->m_map.get (uid);
250
251 if (v)
252 {
253 summary->remove (node, *v);
254
255 if (!summary->m_ggc)
256 delete (*v);
257
258 summary->m_map.remove (uid);
259 }
260 }
261
262 template <typename T>
263 void
264 function_summary<T *>::symtab_duplication (cgraph_node *node,
265 cgraph_node *node2, void *data)
266 {
267 function_summary *summary = (function_summary <T *> *) (data);
268 T *v = summary->get (node);
269
270 if (v)
271 {
272 /* This load is necessary, because we insert a new value! */
273 T *duplicate = summary->allocate_new ();
274 summary->m_map.put (node2->get_uid (), duplicate);
275 summary->duplicate (node, node2, v, duplicate);
276 }
277 }
278
279 template <typename T>
280 void
281 gt_ggc_mx(function_summary<T *>* const &summary)
282 {
283 gcc_checking_assert (summary->m_ggc);
284 gt_ggc_mx (&summary->m_map);
285 }
286
287 template <typename T>
288 void
289 gt_pch_nx(function_summary<T *>* const &summary)
290 {
291 gcc_checking_assert (summary->m_ggc);
292 gt_pch_nx (&summary->m_map);
293 }
294
295 template <typename T>
296 void
297 gt_pch_nx(function_summary<T *>* const& summary, gt_pointer_operator op,
298 void *cookie)
299 {
300 gcc_checking_assert (summary->m_ggc);
301 gt_pch_nx (&summary->m_map, op, cookie);
302 }
303
304 /* An impossible class templated by non-pointers so, which makes sure that only
305 summaries gathering pointers can be created. */
306
307 template <class T>
308 class call_summary
309 {
310 private:
311 call_summary();
312 };
313
314 /* Class to store auxiliary information about call graph edges. */
315
316 template <class T>
317 class GTY((user)) call_summary <T *>
318 {
319 public:
320 /* Default construction takes SYMTAB as an argument. */
321 call_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc),
322 m_initialize_when_cloning (false), m_map (13, ggc), m_released (false),
323 m_symtab (symtab)
324 {
325 m_symtab_removal_hook =
326 symtab->add_edge_removal_hook
327 (call_summary::symtab_removal, this);
328 m_symtab_duplication_hook =
329 symtab->add_edge_duplication_hook
330 (call_summary::symtab_duplication, this);
331 }
332
333 /* Destructor. */
334 virtual ~call_summary ()
335 {
336 release ();
337 }
338
339 /* Destruction method that can be called for GGT purpose. */
340 void release ();
341
342 /* Traverses all summarys with a function F called with
343 ARG as argument. */
344 template<typename Arg, bool (*f)(const T &, Arg)>
345 void traverse (Arg a) const
346 {
347 m_map.traverse <f> (a);
348 }
349
350 /* Basic implementation of removal operation. */
351 virtual void remove (cgraph_edge *, T *) {}
352
353 /* Basic implementation of duplication operation. */
354 virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {}
355
356 /* Allocates new data that are stored within map. */
357 T* allocate_new ()
358 {
359 /* Call gcc_internal_because we do not want to call finalizer for
360 a type T. We call dtor explicitly. */
361 return m_ggc ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ;
362 }
363
364 /* Release an item that is stored within map. */
365 void release (T *item);
366
367 /* Getter for summary callgraph edge pointer.
368 If a summary for an edge does not exist, it will be created. */
369 T* get_create (cgraph_edge *edge)
370 {
371 bool existed;
372 T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
373 if (!existed)
374 *v = allocate_new ();
375
376 return *v;
377 }
378
379 /* Getter for summary callgraph edge pointer. */
380 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
381 {
382 T **v = m_map.get (edge->get_uid ());
383 return v == NULL ? NULL : *v;
384 }
385
386 /* Remove edge from summary. */
387 void remove (cgraph_edge *edge)
388 {
389 int uid = edge->get_uid ();
390 T **v = m_map.get (uid);
391 if (v)
392 {
393 m_map.remove (uid);
394 release (*v);
395 }
396 }
397
398 /* Return number of elements handled by data structure. */
399 size_t elements ()
400 {
401 return m_map.elements ();
402 }
403
404 /* Return true if a summary for the given EDGE already exists. */
405 bool exists (cgraph_edge *edge)
406 {
407 return m_map.get (edge->get_uid ()) != NULL;
408 }
409
410 /* Symbol removal hook that is registered to symbol table. */
411 static void symtab_removal (cgraph_edge *edge, void *data);
412
413 /* Symbol duplication hook that is registered to symbol table. */
414 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
415 void *data);
416
417 protected:
418 /* Indication if we use ggc summary. */
419 bool m_ggc;
420
421 /* Initialize summary for an edge that is cloned. */
422 bool m_initialize_when_cloning;
423
424 private:
425 typedef int_hash <int, 0, -1> map_hash;
426
427 /* Main summary store, where summary ID is used as key. */
428 hash_map <map_hash, T *> m_map;
429 /* Internal summary removal hook pointer. */
430 cgraph_edge_hook_list *m_symtab_removal_hook;
431 /* Internal summary duplication hook pointer. */
432 cgraph_2edge_hook_list *m_symtab_duplication_hook;
433 /* Indicates if the summary is released. */
434 bool m_released;
435 /* Symbol table the summary is registered to. */
436 symbol_table *m_symtab;
437
438 template <typename U> friend void gt_ggc_mx (call_summary <U *> * const &);
439 template <typename U> friend void gt_pch_nx (call_summary <U *> * const &);
440 template <typename U> friend void gt_pch_nx (call_summary <U *> * const &,
441 gt_pointer_operator, void *);
442 };
443
444 template <typename T>
445 void
446 call_summary<T *>::release ()
447 {
448 if (m_released)
449 return;
450
451 m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
452 m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
453
454 /* Release all summaries. */
455 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
456 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
457 release ((*it).second);
458
459 m_released = true;
460 }
461
462 template <typename T>
463 void
464 call_summary<T *>::release (T *item)
465 {
466 if (m_ggc)
467 {
468 item->~T ();
469 ggc_free (item);
470 }
471 else
472 delete item;
473 }
474
475 template <typename T>
476 void
477 call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
478 {
479 call_summary *summary = (call_summary <T *> *) (data);
480
481 int h_uid = edge->get_uid ();
482 T **v = summary->m_map.get (h_uid);
483
484 if (v)
485 {
486 summary->remove (edge, *v);
487 summary->release (*v);
488 summary->m_map.remove (h_uid);
489 }
490 }
491
492 template <typename T>
493 void
494 call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
495 cgraph_edge *edge2, void *data)
496 {
497 call_summary *summary = (call_summary <T *> *) (data);
498 T *edge1_summary = NULL;
499
500 if (summary->m_initialize_when_cloning)
501 edge1_summary = summary->get_create (edge1);
502 else
503 {
504 T **v = summary->m_map.get (edge1->get_uid ());
505 if (v)
506 {
507 /* This load is necessary, because we insert a new value! */
508 edge1_summary = *v;
509 }
510 }
511
512 if (edge1_summary)
513 {
514 T *duplicate = summary->allocate_new ();
515 summary->m_map.put (edge2->get_uid (), duplicate);
516 summary->duplicate (edge1, edge2, edge1_summary, duplicate);
517 }
518 }
519
520 template <typename T>
521 void
522 gt_ggc_mx(call_summary<T *>* const &summary)
523 {
524 gcc_checking_assert (summary->m_ggc);
525 gt_ggc_mx (&summary->m_map);
526 }
527
528 template <typename T>
529 void
530 gt_pch_nx(call_summary<T *>* const &summary)
531 {
532 gcc_checking_assert (summary->m_ggc);
533 gt_pch_nx (&summary->m_map);
534 }
535
536 template <typename T>
537 void
538 gt_pch_nx(call_summary<T *>* const& summary, gt_pointer_operator op,
539 void *cookie)
540 {
541 gcc_checking_assert (summary->m_ggc);
542 gt_pch_nx (&summary->m_map, op, cookie);
543 }
544
545 #endif /* GCC_SYMBOL_SUMMARY_H */