diff options
Diffstat (limited to 'lib/gcc/arm-none-eabi/13.2.1/plugin/include/symbol-summary.h')
-rw-r--r-- | lib/gcc/arm-none-eabi/13.2.1/plugin/include/symbol-summary.h | 1013 |
1 files changed, 1013 insertions, 0 deletions
diff --git a/lib/gcc/arm-none-eabi/13.2.1/plugin/include/symbol-summary.h b/lib/gcc/arm-none-eabi/13.2.1/plugin/include/symbol-summary.h new file mode 100644 index 0000000..3ed6162 --- /dev/null +++ b/lib/gcc/arm-none-eabi/13.2.1/plugin/include/symbol-summary.h @@ -0,0 +1,1013 @@ +/* Callgraph summary data structure. + Copyright (C) 2014-2023 Free Software Foundation, Inc. + Contributed by Martin Liska + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef GCC_SYMBOL_SUMMARY_H +#define GCC_SYMBOL_SUMMARY_H + +/* Base class for function_summary and fast_function_summary classes. */ + +template <class T> +class function_summary_base +{ +public: + /* Default construction takes SYMTAB as an argument. */ + function_summary_base (symbol_table *symtab, + cgraph_node_hook symtab_insertion, + cgraph_node_hook symtab_removal, + cgraph_2node_hook symtab_duplication + CXX_MEM_STAT_INFO): + m_symtab (symtab), m_symtab_insertion (symtab_insertion), + m_symtab_removal (symtab_removal), + m_symtab_duplication (symtab_duplication), + m_symtab_insertion_hook (NULL), m_symtab_duplication_hook (NULL), + m_allocator ("function summary" PASS_MEM_STAT) + { + enable_insertion_hook (); + m_symtab_removal_hook + = m_symtab->add_cgraph_removal_hook (m_symtab_removal, this); + enable_duplication_hook (); + } + + /* Basic implementation of insert operation. */ + virtual void insert (cgraph_node *, T *) + { + /* In most cases, it makes no sense to create summaries without + initializing them. */ + gcc_unreachable (); + } + + /* Basic implementation of removal operation. */ + virtual void remove (cgraph_node *, T *) {} + + /* Basic implementation of duplication operation. */ + virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) + { + /* It makes no sense to not copy anything during duplication. */ + gcc_unreachable (); + } + + /* Enable insertion hook invocation. */ + void enable_insertion_hook () + { + if (m_symtab_insertion_hook == NULL) + m_symtab_insertion_hook + = m_symtab->add_cgraph_insertion_hook (m_symtab_insertion, this); + } + + /* Enable insertion hook invocation. */ + void disable_insertion_hook () + { + if (m_symtab_insertion_hook != NULL) + { + m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook); + m_symtab_insertion_hook = NULL; + } + } + + /* Enable duplication hook invocation. */ + void enable_duplication_hook () + { + if (m_symtab_duplication_hook == NULL) + m_symtab_duplication_hook + = m_symtab->add_cgraph_duplication_hook (m_symtab_duplication, this); + } + + /* Enable duplication hook invocation. */ + void disable_duplication_hook () + { + if (m_symtab_duplication_hook != NULL) + { + m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook); + m_symtab_duplication_hook = NULL; + } + } + +protected: + /* Allocates new data that are stored within map. */ + T* allocate_new () + { + /* Call gcc_internal_because we do not want to call finalizer for + a type T. We call dtor explicitly. */ + return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () + : m_allocator.allocate () ; + } + + /* Release an item that is stored within map. */ + void release (T *item) + { + if (is_ggc ()) + ggc_delete (item); + else + m_allocator.remove (item); + } + + /* Unregister all call-graph hooks. */ + void unregister_hooks (); + + /* Symbol table the summary is registered to. */ + symbol_table *m_symtab; + + /* Insertion function defined by a summary. */ + cgraph_node_hook m_symtab_insertion; + /* Removal function defined by a summary. */ + cgraph_node_hook m_symtab_removal; + /* Duplication function defined by a summary. */ + cgraph_2node_hook m_symtab_duplication; + + /* Internal summary insertion hook pointer. */ + cgraph_node_hook_list *m_symtab_insertion_hook; + /* Internal summary removal hook pointer. */ + cgraph_node_hook_list *m_symtab_removal_hook; + /* Internal summary duplication hook pointer. */ + cgraph_2node_hook_list *m_symtab_duplication_hook; + +private: + /* Return true when the summary uses GGC memory for allocation. */ + virtual bool is_ggc () = 0; + + /* Object allocator for heap allocation. */ + object_allocator<T> m_allocator; +}; + +template <typename T> +void +function_summary_base<T>::unregister_hooks () +{ + disable_insertion_hook (); + m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook); + disable_duplication_hook (); +} + +/* We want to pass just pointer types as argument for function_summary + template class. */ + +template <class T> +class function_summary +{ +private: + function_summary(); +}; + +/* Function summary is a helper class that is used to associate a data structure + related to a callgraph node. Typical usage can be seen in IPA passes which + create a temporary pass-related structures. The summary class registers + hooks that are triggered when a new node is inserted, duplicated and deleted. + A user of a summary class can ovewrite virtual methods than are triggered by + the summary if such hook is triggered. Apart from a callgraph node, the user + is given a data structure tied to the node. + + The function summary class can work both with a heap-allocated memory and + a memory gained by garbage collected memory. */ + +template <class T> +class GTY((user)) function_summary <T *>: public function_summary_base<T> +{ +public: + /* Default construction takes SYMTAB as an argument. */ + function_summary (symbol_table *symtab, bool ggc = false CXX_MEM_STAT_INFO); + + /* Destructor. */ + virtual ~function_summary (); + + /* Traverses all summarys with a function F called with + ARG as argument. */ + template<typename Arg, bool (*f)(const T &, Arg)> + void traverse (Arg a) const + { + m_map.template traverse <f> (a); + } + + /* Getter for summary callgraph node pointer. If a summary for a node + does not exist it will be created. */ + T* get_create (cgraph_node *node) + { + bool existed; + T **v = &m_map.get_or_insert (node->get_uid (), &existed); + if (!existed) + *v = this->allocate_new (); + + return *v; + } + + /* Getter for summary callgraph node pointer. */ + T* get (cgraph_node *node) ATTRIBUTE_PURE + { + T **v = m_map.get (node->get_uid ()); + return v == NULL ? NULL : *v; + } + + /* Remove node from summary. */ + using function_summary_base<T>::remove; + void remove (cgraph_node *node) + { + int uid = node->get_uid (); + T **v = m_map.get (uid); + if (v) + { + m_map.remove (uid); + this->release (*v); + } + } + + /* Return true if a summary for the given NODE already exists. */ + bool exists (cgraph_node *node) + { + return m_map.get (node->get_uid ()) != NULL; + } + + /* Symbol insertion hook that is registered to symbol table. */ + static void symtab_insertion (cgraph_node *node, void *data); + + /* Symbol removal hook that is registered to symbol table. */ + static void symtab_removal (cgraph_node *node, void *data); + + /* Symbol duplication hook that is registered to symbol table. */ + static void symtab_duplication (cgraph_node *node, cgraph_node *node2, + void *data); + +protected: + /* Indication if we use ggc summary. */ + bool m_ggc; + +private: + /* Indication if we use ggc summary. */ + bool is_ggc () final override + { + return m_ggc; + } + + typedef int_hash <int, 0, -1> map_hash; + + /* Main summary store, where summary ID is used as key. */ + hash_map <map_hash, T *> m_map; + + template <typename U> friend void gt_ggc_mx (function_summary <U *> * const &); + template <typename U> friend void gt_pch_nx (function_summary <U *> * const &); + template <typename U> friend void gt_pch_nx (function_summary <U *> * const &, + gt_pointer_operator, void *); +}; + +template <typename T> +function_summary<T *>::function_summary (symbol_table *symtab, bool ggc + MEM_STAT_DECL): + function_summary_base<T> (symtab, function_summary::symtab_insertion, + function_summary::symtab_removal, + function_summary::symtab_duplication + PASS_MEM_STAT), + m_ggc (ggc), m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT) {} + +template <typename T> +function_summary<T *>::~function_summary () +{ + this->unregister_hooks (); + + /* Release all summaries. */ + typedef typename hash_map <map_hash, T *>::iterator map_iterator; + for (map_iterator it = m_map.begin (); it != m_map.end (); ++it) + this->release ((*it).second); +} + +template <typename T> +void +function_summary<T *>::symtab_insertion (cgraph_node *node, void *data) +{ + gcc_checking_assert (node->get_uid ()); + function_summary *summary = (function_summary <T *> *) (data); + summary->insert (node, summary->get_create (node)); +} + +template <typename T> +void +function_summary<T *>::symtab_removal (cgraph_node *node, void *data) +{ + gcc_checking_assert (node->get_uid ()); + function_summary *summary = (function_summary <T *> *) (data); + summary->remove (node); +} + +template <typename T> +void +function_summary<T *>::symtab_duplication (cgraph_node *node, + cgraph_node *node2, void *data) +{ + function_summary *summary = (function_summary <T *> *) (data); + T *v = summary->get (node); + + if (v) + summary->duplicate (node, node2, v, summary->get_create (node2)); +} + +template <typename T> +void +gt_ggc_mx(function_summary<T *>* const &summary) +{ + gcc_checking_assert (summary->m_ggc); + gt_ggc_mx (&summary->m_map); +} + +template <typename T> +void +gt_pch_nx (function_summary<T *> *const &) +{ + gcc_unreachable (); +} + +template <typename T> +void +gt_pch_nx (function_summary<T *> *const &, gt_pointer_operator, void *) +{ + gcc_unreachable (); +} + +/* Help template from std c++11. */ + +template<typename T, typename U> +struct is_same +{ + static const bool value = false; +}; + +template<typename T> +struct is_same<T,T> //specialization +{ + static const bool value = true; +}; + +/* We want to pass just pointer types as argument for fast_function_summary + template class. */ + +template <class T, class V> +class fast_function_summary +{ +private: + fast_function_summary (); +}; + +/* Function vector summary is a fast implementation of function_summary that + utilizes vector as primary storage of summaries. */ + +template <class T, class V> +class GTY((user)) fast_function_summary <T *, V> + : public function_summary_base<T> +{ +public: + /* Default construction takes SYMTAB as an argument. */ + fast_function_summary (symbol_table *symtab CXX_MEM_STAT_INFO); + + /* Destructor. */ + virtual ~fast_function_summary (); + + /* Traverses all summarys with a function F called with + ARG as argument. */ + template<typename Arg, bool (*f)(const T &, Arg)> + void traverse (Arg a) const + { + for (unsigned i = 0; i < m_vector->length (); i++) + if ((*m_vector[i]) != NULL) + f ((*m_vector)[i], a); + } + + /* Getter for summary callgraph node pointer. If a summary for a node + does not exist it will be created. */ + T* get_create (cgraph_node *node) + { + int id = node->get_summary_id (); + if (id == -1) + id = this->m_symtab->assign_summary_id (node); + + if ((unsigned int)id >= m_vector->length ()) + vec_safe_grow_cleared (m_vector, + this->m_symtab->cgraph_max_summary_id); + + if ((*m_vector)[id] == NULL) + (*m_vector)[id] = this->allocate_new (); + + return (*m_vector)[id]; + } + + /* Getter for summary callgraph node pointer. */ + T* get (cgraph_node *node) ATTRIBUTE_PURE + { + return exists (node) ? (*m_vector)[node->get_summary_id ()] : NULL; + } + + using function_summary_base<T>::remove; + void remove (cgraph_node *node) + { + if (exists (node)) + { + int id = node->get_summary_id (); + this->release ((*m_vector)[id]); + (*m_vector)[id] = NULL; + } + } + + /* Return true if a summary for the given NODE already exists. */ + bool exists (cgraph_node *node) + { + int id = node->get_summary_id (); + return (id != -1 + && (unsigned int)id < m_vector->length () + && (*m_vector)[id] != NULL); + } + + /* Symbol insertion hook that is registered to symbol table. */ + static void symtab_insertion (cgraph_node *node, void *data); + + /* Symbol removal hook that is registered to symbol table. */ + static void symtab_removal (cgraph_node *node, void *data); + + /* Symbol duplication hook that is registered to symbol table. */ + static void symtab_duplication (cgraph_node *node, cgraph_node *node2, + void *data); + +private: + bool is_ggc () final override; + + /* Summary is stored in the vector. */ + vec <T *, V> *m_vector; + + template <typename U> friend void gt_ggc_mx (fast_function_summary <U *, va_gc> * const &); + template <typename U> friend void gt_pch_nx (fast_function_summary <U *, va_gc> * const &); + template <typename U> friend void gt_pch_nx (fast_function_summary <U *, va_gc> * const &, + gt_pointer_operator, void *); +}; + +template <typename T, typename V> +fast_function_summary<T *, V>::fast_function_summary (symbol_table *symtab + MEM_STAT_DECL): + function_summary_base<T> (symtab, + fast_function_summary::symtab_insertion, + fast_function_summary::symtab_removal, + fast_function_summary::symtab_duplication + PASS_MEM_STAT), m_vector (NULL) +{ + vec_alloc (m_vector, 13 PASS_MEM_STAT); +} + +template <typename T, typename V> +fast_function_summary<T *, V>::~fast_function_summary () +{ + this->unregister_hooks (); + + /* Release all summaries. */ + for (unsigned i = 0; i < m_vector->length (); i++) + if ((*m_vector)[i] != NULL) + this->release ((*m_vector)[i]); + vec_free (m_vector); +} + +template <typename T, typename V> +void +fast_function_summary<T *, V>::symtab_insertion (cgraph_node *node, void *data) +{ + gcc_checking_assert (node->get_uid ()); + fast_function_summary *summary = (fast_function_summary <T *, V> *) (data); + summary->insert (node, summary->get_create (node)); +} + +template <typename T, typename V> +void +fast_function_summary<T *, V>::symtab_removal (cgraph_node *node, void *data) +{ + gcc_checking_assert (node->get_uid ()); + fast_function_summary *summary = (fast_function_summary <T *, V> *) (data); + + if (summary->exists (node)) + summary->remove (node); +} + +template <typename T, typename V> +void +fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node, + cgraph_node *node2, + void *data) +{ + fast_function_summary *summary = (fast_function_summary <T *, V> *) (data); + T *v = summary->get (node); + + if (v) + { + T *duplicate = summary->get_create (node2); + summary->duplicate (node, node2, v, duplicate); + } +} + +template <typename T, typename V> +inline bool +fast_function_summary<T *, V>::is_ggc () +{ + return is_same<V, va_gc>::value; +} + +template <typename T> +void +gt_ggc_mx (fast_function_summary<T *, va_heap>* const &) +{ +} + +template <typename T> +void +gt_pch_nx (fast_function_summary<T *, va_heap>* const &) +{ +} + +template <typename T> +void +gt_pch_nx (fast_function_summary<T *, va_heap>* const&, gt_pointer_operator, + void *) +{ +} + +template <typename T> +void +gt_ggc_mx (fast_function_summary<T *, va_gc>* const &summary) +{ + ggc_test_and_set_mark (summary->m_vector); + gt_ggc_mx (summary->m_vector); +} + +template <typename T> +void +gt_pch_nx (fast_function_summary<T *, va_gc> *const &) +{ + gcc_unreachable (); +} + +template <typename T> +void +gt_pch_nx (fast_function_summary<T *, va_gc> *const &, gt_pointer_operator, + void *) +{ + gcc_unreachable (); +} + +/* Base class for call_summary and fast_call_summary classes. */ + +template <class T> +class call_summary_base +{ +public: + /* Default construction takes SYMTAB as an argument. */ + call_summary_base (symbol_table *symtab, cgraph_edge_hook symtab_removal, + cgraph_2edge_hook symtab_duplication CXX_MEM_STAT_INFO): + m_symtab (symtab), m_symtab_removal (symtab_removal), + m_symtab_duplication (symtab_duplication), m_symtab_duplication_hook (NULL), + m_initialize_when_cloning (false), + m_allocator ("call summary" PASS_MEM_STAT) + { + m_symtab_removal_hook + = m_symtab->add_edge_removal_hook (m_symtab_removal, this); + enable_duplication_hook (); + } + + /* Basic implementation of removal operation. */ + virtual void remove (cgraph_edge *, T *) {} + + /* Basic implementation of duplication operation. */ + virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) + { + gcc_unreachable (); + } + + /* Enable duplication hook invocation. */ + void enable_duplication_hook () + { + if (m_symtab_duplication_hook == NULL) + m_symtab_duplication_hook + = m_symtab->add_edge_duplication_hook (m_symtab_duplication, + this); + } + + /* Enable duplication hook invocation. */ + void disable_duplication_hook () + { + if (m_symtab_duplication_hook != NULL) + { + m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook); + m_symtab_duplication_hook = NULL; + } + } + +protected: + /* Allocates new data that are stored within map. */ + T* allocate_new () + { + /* Call gcc_internal_because we do not want to call finalizer for + a type T. We call dtor explicitly. */ + return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () + : m_allocator.allocate (); + } + + /* Release an item that is stored within map. */ + void release (T *item) + { + if (is_ggc ()) + ggc_delete (item); + else + m_allocator.remove (item); + } + + /* Unregister all call-graph hooks. */ + void unregister_hooks (); + + /* Symbol table the summary is registered to. */ + symbol_table *m_symtab; + + /* Removal function defined by a summary. */ + cgraph_edge_hook m_symtab_removal; + /* Duplication function defined by a summary. */ + cgraph_2edge_hook m_symtab_duplication; + + /* Internal summary removal hook pointer. */ + cgraph_edge_hook_list *m_symtab_removal_hook; + /* Internal summary duplication hook pointer. */ + cgraph_2edge_hook_list *m_symtab_duplication_hook; + /* Initialize summary for an edge that is cloned. */ + bool m_initialize_when_cloning; + +private: + /* Return true when the summary uses GGC memory for allocation. */ + virtual bool is_ggc () = 0; + + /* Object allocator for heap allocation. */ + object_allocator<T> m_allocator; +}; + +template <typename T> +void +call_summary_base<T>::unregister_hooks () +{ + m_symtab->remove_edge_removal_hook (m_symtab_removal_hook); + disable_duplication_hook (); +} + +/* An impossible class templated by non-pointers so, which makes sure that only + summaries gathering pointers can be created. */ + +template <class T> +class call_summary +{ +private: + call_summary (); +}; + +/* Class to store auxiliary information about call graph edges. */ + +template <class T> +class GTY((user)) call_summary <T *>: public call_summary_base<T> +{ +public: + /* Default construction takes SYMTAB as an argument. */ + call_summary (symbol_table *symtab, bool ggc = false + CXX_MEM_STAT_INFO) + : call_summary_base<T> (symtab, call_summary::symtab_removal, + call_summary::symtab_duplication PASS_MEM_STAT), + m_ggc (ggc), m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT) {} + + /* Destructor. */ + virtual ~call_summary (); + + /* Traverses all summarys with an edge E called with + ARG as argument. */ + template<typename Arg, bool (*f)(const T &, Arg)> + void traverse (Arg a) const + { + m_map.template traverse <f> (a); + } + + /* Getter for summary callgraph edge pointer. + If a summary for an edge does not exist, it will be created. */ + T* get_create (cgraph_edge *edge) + { + bool existed; + T **v = &m_map.get_or_insert (edge->get_uid (), &existed); + if (!existed) + *v = this->allocate_new (); + + return *v; + } + + /* Getter for summary callgraph edge pointer. */ + T* get (cgraph_edge *edge) ATTRIBUTE_PURE + { + T **v = m_map.get (edge->get_uid ()); + return v == NULL ? NULL : *v; + } + + /* Remove edge from summary. */ + using call_summary_base<T>::remove; + void remove (cgraph_edge *edge) + { + int uid = edge->get_uid (); + T **v = m_map.get (uid); + if (v) + { + m_map.remove (uid); + this->release (*v); + } + } + + /* Return true if a summary for the given EDGE already exists. */ + bool exists (cgraph_edge *edge) + { + return m_map.get (edge->get_uid ()) != NULL; + } + + /* Symbol removal hook that is registered to symbol table. */ + static void symtab_removal (cgraph_edge *edge, void *data); + + /* Symbol duplication hook that is registered to symbol table. */ + static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2, + void *data); + +protected: + /* Indication if we use ggc summary. */ + bool m_ggc; + +private: + /* Indication if we use ggc summary. */ + bool is_ggc () final override + { + return m_ggc; + } + + typedef int_hash <int, 0, -1> map_hash; + + /* Main summary store, where summary ID is used as key. */ + hash_map <map_hash, T *> m_map; + + template <typename U> friend void gt_ggc_mx (call_summary <U *> * const &); + template <typename U> friend void gt_pch_nx (call_summary <U *> * const &); + template <typename U> friend void gt_pch_nx (call_summary <U *> * const &, + gt_pointer_operator, void *); +}; + +template <typename T> +call_summary<T *>::~call_summary () +{ + this->unregister_hooks (); + + /* Release all summaries. */ + typedef typename hash_map <map_hash, T *>::iterator map_iterator; + for (map_iterator it = m_map.begin (); it != m_map.end (); ++it) + this->release ((*it).second); +} + +template <typename T> +void +call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data) +{ + call_summary *summary = (call_summary <T *> *) (data); + summary->remove (edge); +} + +template <typename T> +void +call_summary<T *>::symtab_duplication (cgraph_edge *edge1, + cgraph_edge *edge2, void *data) +{ + call_summary *summary = (call_summary <T *> *) (data); + T *edge1_summary = NULL; + + if (summary->m_initialize_when_cloning) + edge1_summary = summary->get_create (edge1); + else + edge1_summary = summary->get (edge1); + + if (edge1_summary) + summary->duplicate (edge1, edge2, edge1_summary, + summary->get_create (edge2)); +} + +template <typename T> +void +gt_ggc_mx(call_summary<T *>* const &summary) +{ + gcc_checking_assert (summary->m_ggc); + gt_ggc_mx (&summary->m_map); +} + +template <typename T> +void +gt_pch_nx (call_summary<T *> *const &) +{ + gcc_unreachable (); +} + +template <typename T> +void +gt_pch_nx (call_summary<T *> *const &, gt_pointer_operator, void *) +{ + gcc_unreachable (); +} + +/* We want to pass just pointer types as argument for fast_call_summary + template class. */ + +template <class T, class V> +class fast_call_summary +{ +private: + fast_call_summary (); +}; + +/* Call vector summary is a fast implementation of call_summary that + utilizes vector as primary storage of summaries. */ + +template <class T, class V> +class GTY((user)) fast_call_summary <T *, V>: public call_summary_base<T> +{ +public: + /* Default construction takes SYMTAB as an argument. */ + fast_call_summary (symbol_table *symtab CXX_MEM_STAT_INFO) + : call_summary_base<T> (symtab, fast_call_summary::symtab_removal, + fast_call_summary::symtab_duplication PASS_MEM_STAT), + m_vector (NULL) + { + vec_alloc (m_vector, 13 PASS_MEM_STAT); + } + + /* Destructor. */ + virtual ~fast_call_summary (); + + /* Traverses all summarys with an edge F called with + ARG as argument. */ + template<typename Arg, bool (*f)(const T &, Arg)> + void traverse (Arg a) const + { + for (unsigned i = 0; i < m_vector->length (); i++) + if ((*m_vector[i]) != NULL) + f ((*m_vector)[i], a); + } + + /* Getter for summary callgraph edge pointer. + If a summary for an edge does not exist, it will be created. */ + T* get_create (cgraph_edge *edge) + { + int id = edge->get_summary_id (); + if (id == -1) + id = this->m_symtab->assign_summary_id (edge); + + if ((unsigned)id >= m_vector->length ()) + vec_safe_grow_cleared (m_vector, this->m_symtab->edges_max_summary_id); + + if ((*m_vector)[id] == NULL) + (*m_vector)[id] = this->allocate_new (); + + return (*m_vector)[id]; + } + + /* Getter for summary callgraph edge pointer. */ + T* get (cgraph_edge *edge) ATTRIBUTE_PURE + { + return exists (edge) ? (*m_vector)[edge->get_summary_id ()] : NULL; + } + + /* Remove edge from summary. */ + using call_summary_base<T>::remove; + void remove (cgraph_edge *edge) + { + if (exists (edge)) + { + int id = edge->get_summary_id (); + this->release ((*m_vector)[id]); + (*m_vector)[id] = NULL; + } + } + + /* Return true if a summary for the given EDGE already exists. */ + bool exists (cgraph_edge *edge) + { + int id = edge->get_summary_id (); + return (id != -1 + && (unsigned)id < m_vector->length () + && (*m_vector)[id] != NULL); + } + + /* Symbol removal hook that is registered to symbol table. */ + static void symtab_removal (cgraph_edge *edge, void *data); + + /* Symbol duplication hook that is registered to symbol table. */ + static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2, + void *data); + +private: + bool is_ggc () final override; + + /* Summary is stored in the vector. */ + vec <T *, V> *m_vector; + + template <typename U> friend void gt_ggc_mx (fast_call_summary <U *, va_gc> * const &); + template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &); + template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &, + gt_pointer_operator, void *); +}; + +template <typename T, typename V> +fast_call_summary<T *, V>::~fast_call_summary () +{ + this->unregister_hooks (); + + /* Release all summaries. */ + for (unsigned i = 0; i < m_vector->length (); i++) + if ((*m_vector)[i] != NULL) + this->release ((*m_vector)[i]); + vec_free (m_vector); +} + +template <typename T, typename V> +void +fast_call_summary<T *, V>::symtab_removal (cgraph_edge *edge, void *data) +{ + fast_call_summary *summary = (fast_call_summary <T *, V> *) (data); + summary->remove (edge); +} + +template <typename T, typename V> +void +fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1, + cgraph_edge *edge2, void *data) +{ + fast_call_summary *summary = (fast_call_summary <T *, V> *) (data); + T *edge1_summary = NULL; + + if (summary->m_initialize_when_cloning) + edge1_summary = summary->get_create (edge1); + else + edge1_summary = summary->get (edge1); + + if (edge1_summary) + { + T *duplicate = summary->get_create (edge2); + summary->duplicate (edge1, edge2, edge1_summary, duplicate); + } +} + +template <typename T, typename V> +inline bool +fast_call_summary<T *, V>::is_ggc () +{ + return is_same<V, va_gc>::value; +} + +template <typename T> +void +gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED) +{ +} + +template <typename T> +void +gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED) +{ +} + +template <typename T> +void +gt_pch_nx (fast_call_summary<T *, va_heap>* const& summary ATTRIBUTE_UNUSED, + gt_pointer_operator op ATTRIBUTE_UNUSED, + void *cookie ATTRIBUTE_UNUSED) +{ +} + +template <typename T> +void +gt_ggc_mx (fast_call_summary<T *, va_gc>* const &summary) +{ + ggc_test_and_set_mark (summary->m_vector); + gt_ggc_mx (&summary->m_vector); +} + +template <typename T> +void +gt_pch_nx (fast_call_summary<T *, va_gc> *const &) +{ + gcc_unreachable (); +} + +template <typename T> +void +gt_pch_nx (fast_call_summary<T *, va_gc> *const &, gt_pointer_operator, void *) +{ + gcc_unreachable (); +} + +#endif /* GCC_SYMBOL_SUMMARY_H */ |