From be609b5a0edcf2b2865317e71f43af54a5238e59 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 6 Apr 2020 15:49:22 -0400 Subject: [PATCH 007/179] FIXME: initial impl of uniq_manager --- gcc/Makefile.in | 3 +- gcc/analyzer/analyzer-selftests.cc | 1 + gcc/analyzer/analyzer-selftests.h | 1 + gcc/analyzer/uniq-manager.cc | 152 ++++++++++++++++++++++++ gcc/analyzer/uniq-manager.h | 183 +++++++++++++++++++++++++++++ 5 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 gcc/analyzer/uniq-manager.cc create mode 100644 gcc/analyzer/uniq-manager.h diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 3f2a032b67d..a3b3427fea3 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1241,7 +1241,8 @@ ANALYZER_OBJS = \ analyzer/sm-signal.o \ analyzer/sm-taint.o \ analyzer/state-purge.o \ - analyzer/supergraph.o + analyzer/supergraph.o \ + analyzer/uniq-manager.o # Language-independent object files. # We put the *-match.o and insn-*.o files first so that a parallel make diff --git a/gcc/analyzer/analyzer-selftests.cc b/gcc/analyzer/analyzer-selftests.cc index 8e200a3844b..c157bda3bff 100644 --- a/gcc/analyzer/analyzer-selftests.cc +++ b/gcc/analyzer/analyzer-selftests.cc @@ -58,6 +58,7 @@ run_analyzer_selftests () analyzer_region_model_cc_tests (); analyzer_sm_file_cc_tests (); analyzer_sm_signal_cc_tests (); + analyzer_uniq_manager_cc_tests (); #endif /* #if ENABLE_ANALYZER */ } diff --git a/gcc/analyzer/analyzer-selftests.h b/gcc/analyzer/analyzer-selftests.h index 7924b8c8f01..29c2aeae120 100644 --- a/gcc/analyzer/analyzer-selftests.h +++ b/gcc/analyzer/analyzer-selftests.h @@ -41,6 +41,7 @@ extern void analyzer_program_state_cc_tests (); extern void analyzer_region_model_cc_tests (); extern void analyzer_sm_file_cc_tests (); extern void analyzer_sm_signal_cc_tests (); +extern void analyzer_uniq_manager_cc_tests (); } /* end of namespace ana::selftest. */ diff --git a/gcc/analyzer/uniq-manager.cc b/gcc/analyzer/uniq-manager.cc new file mode 100644 index 00000000000..6d878d030c1 --- /dev/null +++ b/gcc/analyzer/uniq-manager.cc @@ -0,0 +1,152 @@ +/* FIXME. + Copyright (C) 2020 Free Software Foundation, Inc. + Contributed by David Malcolm . + +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 +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "selftest.h" +#include "analyzer/uniq-manager.h" + +#if ENABLE_ANALYZER + +namespace ana { + +#if 0 +/* class uniq_id_t. */ + +hashval_t +uniq_id_t::hash () const +{ + hashval_t result = 0; + int i; + char *ch; + FOR_EACH_VEC_ELT (m_data, i, ch) + { + result <<= 8; + result %= ch; + } + // FIXME: better impl + return result; +} + +bool +uniq_id_t::operator== (const uniq_id_t &other) const +{ + if (m_data.length () != other.m_data.length ()) + return false; + return memcmp (&m_data[0], &other.m_data[0], m_data.length ()) == 0; +} +#endif + +#if CHECKING_P + +namespace selftest { + +class counted +{ +public: + counted (unsigned *inst_counter) + : m_inst_counter (inst_counter) + { + (*m_inst_counter)++; + } + ~counted () + { + (*m_inst_counter)--; + } +private: + unsigned *m_inst_counter; +}; + +class int_wrapper : public counted +{ +public: + int_wrapper (unsigned *inst_counter, int val) + : counted (inst_counter), m_val (val) {} + + hashval_t hash () const { return m_val; } + bool operator== (const int_wrapper& other) const + { + return m_val == other.m_val; + } + +#if 0 + void add_to_uniq_id (uniq_id_t *out) const + { + out->add_int (m_val); + } +#endif + +private: + int m_val; +}; + +/* FIXME. */ + +static void +test_int_wrapper () +{ + unsigned inst_counter = 0; + + { + uniq_manager m; + ASSERT_EQ (m.get_count (), 0); + + int_wrapper *init_w0 = new int_wrapper (&inst_counter, 0); + ASSERT_EQ (inst_counter, 1); + const int_wrapper *cw0 = m.consolidate (init_w0); + ASSERT_EQ (init_w0, cw0); + ASSERT_EQ (m.get_count (), 1); + + int_wrapper *w1 = new int_wrapper (&inst_counter, 1); + ASSERT_EQ (inst_counter, 2); + const int_wrapper *cw1 = m.consolidate (w1); + ASSERT_EQ (w1, cw1); + ASSERT_EQ (m.get_count (), 2); + + /* Consolidating another instance of "0" should give us back the initial + instance of 0, and delete the new one. */ + int_wrapper *another_w0 = new int_wrapper (&inst_counter, 0); + ASSERT_EQ (inst_counter, 3); + const int_wrapper *another_cw0 = m.consolidate (another_w0); + ASSERT_EQ (inst_counter, 2); + ASSERT_EQ (init_w0, another_cw0); + ASSERT_EQ (m.get_count (), 2); + } + + /* All instance should be cleaned up when the manager is destroyed. */ + ASSERT_EQ (inst_counter, 0); +} + +/* Run all of the selftests within this file. */ + +void +analyzer_uniq_manager_cc_tests () +{ + test_int_wrapper (); +} + +} // namespace selftest + +#endif /* CHECKING_P */ + +} // namespace ana + +#endif /* #if ENABLE_ANALYZER */ diff --git a/gcc/analyzer/uniq-manager.h b/gcc/analyzer/uniq-manager.h new file mode 100644 index 00000000000..c56630d7d61 --- /dev/null +++ b/gcc/analyzer/uniq-manager.h @@ -0,0 +1,183 @@ +/* FIXME. + Copyright (C) 2020 Free Software Foundation, Inc. + Contributed by David Malcolm . + +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 +. */ + +#ifndef GCC_ANALYZER_UNIQ_MANAGER_H +#define GCC_ANALYZER_UNIQ_MANAGER_H + +#if ENABLE_ANALYZER + +namespace ana { + +#if 0 +class uniq_id_t +{ +public: + hashval_t hash () const; + bool operator== (const uniq_id_t &other) const; + + bool add_int (int val); + +private: + // TODO: need copy-ctor etc + auto_vec m_data; +}; +#endif + +#if 0 +class hash_visitor +{ +public: + bool on_int (int val) + { + m_hash ^= val; + return true; + } + +private: + hashval_t m_hash; +}; +class eq_visitor +{ +public: + bool on_int (int val) + { + } +} +#endif + +/* A class responsible for ensuring that instances of a class + that are sufficiently similar are unique. + + FIXME: T should implement a get_id (instance_manager *id) method. + + T should implement the following: + hashval_t hash () const; + bool operator== (const T &other) const; + + FIXME: or maybe a visit_fields method? */ +template +class uniq_manager +{ + public: +#if 0 + struct map_value + { + uniq_id_t m_id; + T *m_unique_val; + }; + typedef hash_map map_t; +#endif + struct traits_t + { + //typedef uniq_id_t *key_type; + typedef T *key_type; + typedef T *value_type; + typedef T *compare_type; + + static inline hashval_t hash (const key_type &k) + { + gcc_assert (k != NULL); + return k->hash (); + } + static inline bool equal_keys (const key_type &k1, const key_type &k2) + { + gcc_assert (k1 != NULL); + gcc_assert (k2 != NULL); + return *k1 == *k2; + } + template + static inline void remove (E &entry) + { + delete entry.m_key; + } + template + static inline void mark_deleted (E &entry) + { + entry.m_key = reinterpret_cast (1); + } + template + static inline void mark_empty (E &entry) + { + entry.m_key = NULL; + } + template + static inline bool is_deleted (const E &entry) + { + return entry.m_key == reinterpret_cast (1); + } + template + static inline bool is_empty (const E &entry) + { + return entry.m_key == NULL; + } + static const bool empty_zero_p = true; + }; + //typedef hash_map map_t; + typedef hash_map map_t; + typedef typename map_t::iterator iterator_t; + + /* Takes ownership of t, deleting it if there's a duplicate. */ + const T *consolidate (T *t) + { +#if 1 + gcc_assert (t); + //uniq_id_t *id = new uniq_id_t (); + //t->add_to_uniq_id (id); + bool existed; + T *&ptr = m_map.get_or_insert (t, &existed); // FIXME: hash function! + if (existed) + { + //delete id; + delete t; + return ptr; + } + else + { + ptr = t; + return t; + } +#else + uniq_id_t id; + t->get_id (&id); + if (map_value *slot = m_map.get (&id)) // FIXME: hash function! + { + delete t; + return slot->m_unique_val; + } + else + { + slot->m_id = id; + slot->m_unique_val = t; + } +#endif + } + + /* How many T are being managed. */ + size_t get_count () const { return m_map.elements (); } + + private: + map_t m_map; +}; + +#endif /* CHECKING_P */ + +} // namespace ana + +#endif /* GCC_ANALYZER_UNIQ_MANAGER_H */ -- 2.21.0