diff options
Diffstat (limited to 'lib/gcc/arm-none-eabi/13.2.1/plugin/include/hash-map.h')
-rw-r--r-- | lib/gcc/arm-none-eabi/13.2.1/plugin/include/hash-map.h | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/lib/gcc/arm-none-eabi/13.2.1/plugin/include/hash-map.h b/lib/gcc/arm-none-eabi/13.2.1/plugin/include/hash-map.h new file mode 100644 index 0000000..1c5189b --- /dev/null +++ b/lib/gcc/arm-none-eabi/13.2.1/plugin/include/hash-map.h @@ -0,0 +1,388 @@ +/* A type-safe hash map. + Copyright (C) 2014-2023 Free Software Foundation, Inc. + +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 hash_map_h +#define hash_map_h + +/* Class hash_map is a hash-value based container mapping objects of + KeyId type to those of the Value type. + Both KeyId and Value may be non-trivial (non-POD) types provided + a suitabe Traits class. A few default Traits specializations are + provided for basic types such as integers, pointers, and std::pair. + Inserted elements are value-initialized either to zero for POD types + or by invoking their default ctor. Removed elements are destroyed + by invoking their dtor. On hash_map destruction all elements are + removed. Objects of hash_map type are copy-constructible but not + assignable. */ + +const size_t default_hash_map_size = 13; +template<typename KeyId, typename Value, + typename Traits /* = simple_hashmap_traits<default_hash_traits<Key>, + Value> */> +class GTY((user)) hash_map +{ + typedef typename Traits::key_type Key; + struct hash_entry + { + Key m_key; + Value m_value; + + typedef hash_entry value_type; + typedef Key compare_type; + + static hashval_t hash (const hash_entry &e) + { + return Traits::hash (e.m_key); + } + + static bool equal (const hash_entry &a, const Key &b) + { + return Traits::equal_keys (a.m_key, b); + } + + static void remove (hash_entry &e) { Traits::remove (e); } + + static void mark_deleted (hash_entry &e) { Traits::mark_deleted (e); } + + static bool is_deleted (const hash_entry &e) + { + return Traits::is_deleted (e); + } + + static const bool empty_zero_p = Traits::empty_zero_p; + static void mark_empty (hash_entry &e) { Traits::mark_empty (e); } + static bool is_empty (const hash_entry &e) { return Traits::is_empty (e); } + + static void ggc_mx (hash_entry &e) + { + gt_ggc_mx (e.m_key); + gt_ggc_mx (e.m_value); + } + + static void ggc_maybe_mx (hash_entry &e) + { + if (Traits::maybe_mx) + ggc_mx (e); + } + + static void pch_nx (hash_entry &e) + { + gt_pch_nx (e.m_key); + gt_pch_nx (e.m_value); + } + + static void pch_nx (hash_entry &e, gt_pointer_operator op, void *c) + { + pch_nx_helper (e.m_key, op, c); + pch_nx_helper (e.m_value, op, c); + } + + static int keep_cache_entry (hash_entry &e) + { + return ggc_marked_p (e.m_key); + } + + private: + template<typename T> + static void + pch_nx_helper (T &x, gt_pointer_operator op, void *cookie) + { + gt_pch_nx (&x, op, cookie); + } + + template<typename T> + static void + pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie) + { + op (&x, NULL, cookie); + } + + /* The overloads below should match those in ggc.h. */ +#define DEFINE_PCH_HELPER(T) \ + static void pch_nx_helper (T, gt_pointer_operator, void *) { } + + DEFINE_PCH_HELPER (bool); + DEFINE_PCH_HELPER (char); + DEFINE_PCH_HELPER (signed char); + DEFINE_PCH_HELPER (unsigned char); + DEFINE_PCH_HELPER (short); + DEFINE_PCH_HELPER (unsigned short); + DEFINE_PCH_HELPER (int); + DEFINE_PCH_HELPER (unsigned int); + DEFINE_PCH_HELPER (long); + DEFINE_PCH_HELPER (unsigned long); + DEFINE_PCH_HELPER (long long); + DEFINE_PCH_HELPER (unsigned long long); + +#undef DEFINE_PCH_HELPER + }; + +public: + explicit hash_map (size_t n = default_hash_map_size, bool ggc = false, + bool sanitize_eq_and_hash = true, + bool gather_mem_stats = GATHER_STATISTICS + CXX_MEM_STAT_INFO) + : m_table (n, ggc, sanitize_eq_and_hash, gather_mem_stats, + HASH_MAP_ORIGIN PASS_MEM_STAT) + { + } + + explicit hash_map (const hash_map &h, bool ggc = false, + bool sanitize_eq_and_hash = true, + bool gather_mem_stats = GATHER_STATISTICS + CXX_MEM_STAT_INFO) + : m_table (h.m_table, ggc, sanitize_eq_and_hash, gather_mem_stats, + HASH_MAP_ORIGIN PASS_MEM_STAT) {} + + /* Create a hash_map in ggc memory. */ + static hash_map *create_ggc (size_t size = default_hash_map_size, + bool gather_mem_stats = GATHER_STATISTICS + CXX_MEM_STAT_INFO) + { + hash_map *map = ggc_alloc<hash_map> (); + new (map) hash_map (size, true, true, gather_mem_stats PASS_MEM_STAT); + return map; + } + + /* If key k isn't already in the map add key k with value v to the map, and + return false. Otherwise set the value of the entry for key k to be v and + return true. */ + + bool put (const Key &k, const Value &v) + { + hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k), + INSERT); + bool ins = Traits::is_empty (*e); + if (ins) + { + e->m_key = k; + new ((void *)&e->m_value) Value (v); + gcc_checking_assert (!Traits::is_empty (*e) + && !Traits::is_deleted (*e)); + } + else + e->m_value = v; + + return !ins; + } + + /* If the passed in key is in the map return pointer to its value + otherwise NULL. */ + + Value *get (const Key &k) + { + hash_entry &e = m_table.find_with_hash (k, Traits::hash (k)); + return Traits::is_empty (e) ? NULL : &e.m_value; + } + + /* Return a reference to the value for the passed in key, creating the entry + if it doesn't already exist. If existed is not NULL then it is set to + false if the key was not previously in the map, and true otherwise. */ + + Value &get_or_insert (const Key &k, bool *existed = NULL) + { + hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k), + INSERT); + bool ins = Traits::is_empty (*e); + if (ins) + { + e->m_key = k; + new ((void *)&e->m_value) Value (); + gcc_checking_assert (!Traits::is_empty (*e) + && !Traits::is_deleted (*e)); + } + + if (existed != NULL) + *existed = !ins; + + return e->m_value; + } + + void remove (const Key &k) + { + m_table.remove_elt_with_hash (k, Traits::hash (k)); + } + + /* Call the call back on each pair of key and value with the passed in + arg until either the call back returns false or all pairs have been seen. + The traversal is unordered. */ + + template<typename Arg, bool (*f)(const typename Traits::key_type &, + const Value &, Arg)> + void traverse (Arg a) const + { + for (typename hash_table<hash_entry>::iterator iter = m_table.begin (); + iter != m_table.end (); ++iter) + if (!f ((*iter).m_key, (*iter).m_value, a)) + break; + } + + template<typename Arg, bool (*f)(const typename Traits::key_type &, + Value *, Arg)> + void traverse (Arg a) const + { + for (typename hash_table<hash_entry>::iterator iter = m_table.begin (); + iter != m_table.end (); ++iter) + if (!f ((*iter).m_key, &(*iter).m_value, a)) + break; + } + + size_t elements () const { return m_table.elements (); } + + void empty () { m_table.empty(); } + + /* Return true when there are no elements in this hash map. */ + bool is_empty () const { return m_table.is_empty (); } + + class iterator + { + public: + explicit iterator (const typename hash_table<hash_entry>::iterator &iter) : + m_iter (iter) {} + + iterator &operator++ () + { + ++m_iter; + return *this; + } + + /* Can't use std::pair here, because GCC before 4.3 don't handle + std::pair where template parameters are references well. + See PR86739. */ + class reference_pair { + public: + const Key &first; + Value &second; + + reference_pair (const Key &key, Value &value) : first (key), second (value) {} + + template <typename K, typename V> + operator std::pair<K, V> () const { return std::pair<K, V> (first, second); } + }; + + reference_pair operator* () + { + hash_entry &e = *m_iter; + return reference_pair (e.m_key, e.m_value); + } + + bool operator== (const iterator &other) const + { + return m_iter == other.m_iter; + } + + bool operator != (const iterator &other) const + { + return m_iter != other.m_iter; + } + + private: + typename hash_table<hash_entry>::iterator m_iter; + }; + + /* Standard iterator retrieval methods. */ + + iterator begin () const { return iterator (m_table.begin ()); } + iterator end () const { return iterator (m_table.end ()); } + +private: + + template<typename T, typename U, typename V> friend void gt_ggc_mx (hash_map<T, U, V> *); + template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *); + template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *); + template<typename T, typename U, typename V> friend void gt_cleare_cache (hash_map<T, U, V> *); + + hash_table<hash_entry> m_table; +}; + +/* ggc marking routines. */ + +template<typename K, typename V, typename H> +inline void +gt_ggc_mx (hash_map<K, V, H> *h) +{ + gt_ggc_mx (&h->m_table); +} + +template<typename K, typename V, typename H> +inline void +gt_pch_nx (hash_map<K, V, H> *h) +{ + gt_pch_nx (&h->m_table); +} + +template<typename K, typename V, typename H> +inline void +gt_cleare_cache (hash_map<K, V, H> *h) +{ + if (h) + gt_cleare_cache (&h->m_table); +} + +template<typename K, typename V, typename H> +inline void +gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie) +{ + op (&h->m_table.m_entries, NULL, cookie); +} + +enum hm_alloc { hm_heap = false, hm_ggc = true }; +template<bool ggc, typename K, typename V, typename H> +inline hash_map<K,V,H> * +hash_map_maybe_create (hash_map<K,V,H> *&h, + size_t size = default_hash_map_size) +{ + if (!h) + { + if (ggc) + h = hash_map<K,V,H>::create_ggc (size); + else + h = new hash_map<K,V,H> (size); + } + return h; +} + +/* Like h->get, but handles null h. */ +template<typename K, typename V, typename H> +inline V* +hash_map_safe_get (hash_map<K,V,H> *h, const K& k) +{ + return h ? h->get (k) : NULL; +} + +/* Like h->get, but handles null h. */ +template<bool ggc, typename K, typename V, typename H> +inline V& +hash_map_safe_get_or_insert (hash_map<K,V,H> *&h, const K& k, bool *e = NULL, + size_t size = default_hash_map_size) +{ + return hash_map_maybe_create<ggc> (h, size)->get_or_insert (k, e); +} + +/* Like h->put, but handles null h. */ +template<bool ggc, typename K, typename V, typename H> +inline bool +hash_map_safe_put (hash_map<K,V,H> *&h, const K& k, const V& v, + size_t size = default_hash_map_size) +{ + return hash_map_maybe_create<ggc> (h, size)->put (k, v); +} + +#endif |