From: Roland McGrath Date: Fri, 10 Jul 2009 23:10:54 +0000 (-0700) Subject: All pieces of dwarf_output in the collector, but refs still not right. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c58d5a90e7f616b7b27196e984e55ec2d6a80b87;p=thirdparty%2Felfutils.git All pieces of dwarf_output in the collector, but refs still not right. --- diff --git a/libdw/c++/data-values.hh b/libdw/c++/data-values.hh index a16bb5f67..86049e2e7 100644 --- a/libdw/c++/data-values.hh +++ b/libdw/c++/data-values.hh @@ -53,7 +53,6 @@ namespace elfutils { - template dwarf::value_space dwarf_data::attr_value::what_space () const @@ -91,5 +90,14 @@ namespace elfutils throw std::runtime_error ("XXX impossible"); } + template + static inline std::string + attribute_string (const attr_pair &attr) + { + std::string result = dwarf::attributes::name (attr.first); + result += "="; + result += attr.second.to_string (); + return result; + } }; diff --git a/libdw/c++/dwarf_data b/libdw/c++/dwarf_data index 94c64f981..6b4c8e616 100644 --- a/libdw/c++/dwarf_data +++ b/libdw/c++/dwarf_data @@ -78,11 +78,13 @@ namespace elfutils typedef std::list _base; // Constructor copying CUs from input container. - template - inline compile_units (const input &other, tracker &t) - { - subr::create_container (this, other, t); - } + template + inline compile_units (const input &other, arg_type &arg) + : _base (subr::argify + (other.begin (), arg), + subr::argify + (other.end (), arg)) + {} public: // Default constructor: an empty container, no CUs. @@ -103,25 +105,31 @@ namespace elfutils template class compile_unit : public impl::debug_info_entry { - friend class subr::create_container; - friend class impl::compile_units; private: - - template - inline void set (const die_type &die, arg_type &arg) + template + inline const input &require_cu (const input &cu) { - if (die.tag () != ::DW_TAG_compile_unit) - throw std::invalid_argument ("not a compile_unit entry"); - impl::debug_info_entry::set (die, arg); + if (cu.tag () != ::DW_TAG_compile_unit) + throw std::runtime_error + ("top-level debug_info_entry must be DW_TAG_compile_unit"); + return cu; } + public: explicit inline compile_unit () : impl::debug_info_entry () { this->_m_tag = ::DW_TAG_compile_unit; } - public: + inline compile_unit (const compile_unit &other) + : impl::debug_info_entry (require_cu (other)) + {} + + template + inline compile_unit (const input &cu, arg_type &arg) + : impl::debug_info_entry (require_cu (cu), arg) + {} // Fetch the CU's DW_AT_stmt_list. inline const typename impl::line_info_table &line_info () const @@ -1456,10 +1464,9 @@ namespace elfutils : public std::map { friend class impl::debug_info_entry; - private: + protected: typedef std::map base_type; - protected: inline attributes_type () {} template diff --git a/libdw/c++/dwarf_edit b/libdw/c++/dwarf_edit index ac0a30b42..badb71d00 100644 --- a/libdw/c++/dwarf_edit +++ b/libdw/c++/dwarf_edit @@ -254,7 +254,21 @@ namespace elfutils typedef debug_info_entry::attributes_type::value_type attribute; - typedef dwarf_data::compile_unit compile_unit; + class compile_unit + : public dwarf_data::compile_unit + { + friend class subr::create_container; + friend class compile_units; + private: + + template + inline void set (const die_type &die, arg_type &arg) + { + if (die.tag () != ::DW_TAG_compile_unit) + throw std::invalid_argument ("not a compile_unit entry"); + debug_info_entry::set (die, arg); + } + }; // Main container anchoring all the output. class compile_units @@ -263,12 +277,6 @@ namespace elfutils friend class dwarf_edit; private: - // Constructor copying CUs from input container. - template - inline compile_units (const input &other, tracker &t) - : dwarf_data::compile_units (other, t) - {} - inline compile_units (const compile_units &) : dwarf_data::compile_units () { @@ -276,6 +284,13 @@ namespace elfutils ("must copy-construct top-level dwarf_edit object instead"); } + // Constructor copying CUs from input container. + template + inline compile_units (const input &other, tracker &t) + { + subr::create_container (this, other, t); + } + public: // Default constructor: an empty container, no CUs. inline compile_units () {} diff --git a/libdw/c++/dwarf_output b/libdw/c++/dwarf_output index b688b38b4..bb5039222 100644 --- a/libdw/c++/dwarf_output +++ b/libdw/c++/dwarf_output @@ -74,207 +74,6 @@ namespace elfutils { class dwarf_output_collector; -#if 0 - class dwarf_output - { - public: - class compile_units; - class debug_info_entry; - typedef debug_info_entry compile_unit; - - private: - template - static inline const input & - collect (dwarf_output_collector &c, - const subr::auto_ref &p) - { - return static_cast (p); - } - - template - static inline const debug_info_entry & - collect (dwarf_output_collector &, - const typename input::debug_info_entry &); - - public: - - // XXX later - class attr_value : public dwarf::attr_value - { - public: - attr_value (const dwarf::attr_value &v) : dwarf::attr_value (v) {} - }; - - class debug_info_entry - { - friend class dwarf_output; - - public: - typedef subr::hashed_unordered_map attributes_type; - typedef subr::hashed_vector children_type; - - private: - const int _m_tag; - const attributes_type _m_attributes; - const children_type _m_children; - size_t _m_hash; - - /* The template constructor lets us copy in from any class that has - compatibly iterable containers for attributes and children. */ - template - debug_info_entry (const die_type &die, dwarf_output_collector &c) - : _m_tag (die.tag ()), - _m_attributes (die.attributes ()), - _m_children (die.children ()), - _m_hash (0) - { - subr::hash_combine (_m_hash, _m_tag); - subr::hash_combine (_m_hash, _m_attributes); - subr::hash_combine (_m_hash, _m_children); - } - - public: - inline int tag () const - { - return _m_tag; - } - - inline bool has_children () const - { - return !_m_children.empty (); - } - - inline const children_type &children () const - { - return _m_children; - } - - inline const attributes_type &attributes () const - { - return _m_attributes; - } - - template - bool operator== (const die &other) const - { - return (other.attributes () == attributes () - && other.children () == children ()); - } - template - bool operator!= (const die &other) const - { - return !(*this == other); - } - }; - - typedef debug_info_entry::attributes_type::value_type attribute; - - public: - /* Main container anchoring all the output. - - This is the only container that actually lives in the dwarf_output - object. All others live in the dwarf_output_collector's sets, and - we return const references to those copies. - - This vector is actually mutable as a std::vector. But note that you - should never remove a compile_unit, though you can reorder the - vector. Nothing is ever removed from the collector, so your final - output file can wind up with unreferenced data being encoded. If - you do remove any elements, then you should start a fresh collector - and construct a new dwarf_output object by copying using that - collector (or, equivalently, call o.compile_units ().recollect (C) - on the new collector C). */ - class compile_units - : public std::vector > - { - friend class dwarf_output; - private: - typedef std::vector > _base; - - template - struct make - : public std::binary_function - { - _base::value_type operator () (const typename input::value_type &cu, - dwarf_output_collector &c) const - { - return _base::value_type (collect (c, cu)); - } - }; - - // Construct empty container. - compile_units () - : _base () - {} - - // Constructor copying CUs from input container. - template - compile_units (const input &units, dwarf_output_collector &c) - : _base () - { - for (typename input::const_iterator it = units.begin (); - it != units.end (); - ++it) - push_back (make () (*it, c)); - } - - public: - template - bool operator== (const other_children &other) const - { - return subr::container_equal (*this, other); - } - template - bool operator!= (const other_children &other) const - { - return !(*this == other); - } - - void recollect (dwarf_output_collector &c) - { - std::transform (begin (), end (), begin (), - std::bind2nd (make (), c)); - } - }; - - private: - const compile_units _m_units; - - public: - const class compile_units &compile_units () const - { - return _m_units; - } - - public: - // Constructor for an empty file, can add to its compile_units (). - dwarf_output () - : _m_units () - {} - - // Constructor copying CUs from an input file (can be any of dwarf, - // dwarf_edit, or dwarf_output). - template - dwarf_output (const input &dw, dwarf_output_collector &c) - : _m_units (dw.compile_units (), c) - {} - - template - inline bool operator== (const file &other) const - { - return compile_units () == other.compile_units (); - } - template - inline bool operator!= (const file &other) const - { - return !(*this == other); - } - }; - -#else // XXX temp - class dwarf_output { friend class dwarf_output_collector; @@ -295,6 +94,12 @@ namespace elfutils class attr_value; protected: + static inline void never_copy () + { + throw std::logic_error + ("must copy-construct top-level dwarf_output object instead"); + } + template class copier; // Below. #if 0 @@ -433,7 +238,6 @@ namespace elfutils class debug_info_entry { friend class dwarf_output_collector; - friend class subr::create_container; public: class attributes_type @@ -472,7 +276,7 @@ namespace elfutils subr::hash_combine (_m_hash, *i); } - inline bool are (const attributes_type &these) const + inline bool is (const attributes_type &these) const { return (_m_hash == these._m_hash && size () == these.size () @@ -481,66 +285,123 @@ namespace elfutils } }; - class children_type : public std::list + class children_type + : public std::vector { friend class debug_info_entry; - private: + protected: + typedef std::vector _base; + + size_t _m_hash; + inline children_type () {} - template - static inline void - copied (const iterator &out, const typename input::const_iterator &in, - bool last_sibling, copier &c) + struct deref + : public std::unary_function { - c.copied (out, in, last_sibling); - } + inline deref (...) {} + + inline const debug_info_entry & + operator () (const debug_info_entry *x) const + { + return *x; + } + }; + + public: + friend class subr::hashed_hasher; + typedef subr::hashed_hasher hasher; + + typedef debug_info_entry value_type; + typedef debug_info_entry &reference; + typedef debug_info_entry &const_reference; + typedef debug_info_entry *pointer; + typedef debug_info_entry *const_pointer; template inline children_type (const input &other, copier &c) + : _base (), _m_hash (0) { - subr::create_container (this, other, c, copied); + typename input::const_iterator in = other.begin (); + bool has_sibling = in != other.end (); + while (has_sibling) + { + const typename input::const_iterator here = in++; + has_sibling = in != other.end (); + const debug_info_entry *child = c.add_entry (*here, has_sibling); + subr::hash_combine (_m_hash, (uintptr_t) child); + push_back (child); + c.copied (--end (), here, has_sibling); + } } - public: - typedef debug_info_entry value_type; + inline bool is (const children_type &these) const + { + return (_m_hash == these._m_hash + && size () == these.size () + && std::equal (_base::begin (), _base::end (), + these._base::begin ())); + } + + typedef subr::wrapped_input_iterator< + _base, deref, const debug_info_entry> const_iterator; + typedef const_iterator iterator; + + inline const_iterator begin () const + { + return const_iterator (_base::begin (), subr::nothing ()); + } + + inline const_iterator end () const + { + return const_iterator (_base::end (), subr::nothing ()); + } }; typedef children_type::iterator pointer; typedef children_type::const_iterator const_pointer; protected: - int _m_tag; + const children_type *_m_children; const attributes_type *_m_attributes; - children_type _m_children; void *_m_shape; + size_t _m_hash; + int _m_tag; // This is can only be used by the children_type constructor, // which immediately calls set. inline debug_info_entry () - : _m_tag (-1), _m_attributes (NULL), _m_children (), _m_shape (NULL) + : _m_children (NULL), + _m_attributes (NULL), + _m_shape (NULL), + _m_hash (0), + _m_tag (-1) {} template - inline void set (const die_type &die, copier &c) + inline debug_info_entry (const die_type &die, copier &c) + : _m_children (c.add_children (die.children ())), + _m_attributes (c.add_attributes (die.attributes ())), + _m_shape (NULL), // XXX + _m_hash (die.tag ()), + _m_tag (die.tag ()) { - assert (_m_attributes == NULL); - try - { - _m_tag = die.tag (); - _m_attributes = c.add_attributes (die.attributes ()); - _m_children.swap (children_type (die.children (), c)); - } - catch (...) - { - // Never leave a partially-formed DIE. - _m_tag = -1; - _m_attributes = NULL; - _m_children.clear (); - throw; - }; + subr::hash_combine (_m_hash, *_m_attributes); + subr::hash_combine (_m_hash, *_m_children); } public: + friend class subr::hashed_hasher; + typedef subr::hashed_hasher hasher; + + inline bool is (const debug_info_entry &that) const + { + return (_m_hash == that._m_hash + && _m_tag == that._m_tag + && _m_attributes == that._m_attributes + && _m_children == that._m_children); + } inline int tag () const { @@ -549,12 +410,12 @@ namespace elfutils inline bool has_children () const { - return !_m_children.empty (); + return !_m_children->empty (); } inline const children_type &children () const { - return _m_children; + return *_m_children; } inline const attributes_type &attributes () const @@ -593,6 +454,7 @@ namespace elfutils typedef dwarf_data::attr_value _base; public: + inline std::string to_string () const; /* These constructors can only be used by the containers used in the collector. The attributes_type map in an @@ -639,26 +501,38 @@ namespace elfutils typedef dwarf_data::compile_unit compile_unit; - // Main container anchoring all the output. + /* Main container anchoring all the output. + + This is the only container that actually lives in the dwarf_output + object. All others live in the dwarf_output_collector's sets, and + we return const references to those copies. + + This list is actually mutable as a std::list. But note that you + should never remove a compile_unit, though you can reorder the + list. Nothing is ever removed from the collector, so your final + output file can wind up with unreferenced data being encoded. If + you do remove any elements, then you should start a fresh collector + and construct a new dwarf_output object by copying using that + collector (or, equivalently, call o.compile_units ().recollect (C) + on the new collector C). */ class compile_units : public dwarf_data::compile_units { friend class dwarf_output; private: + inline compile_units (const compile_units &) + : dwarf_data::compile_units () + { + never_copy (); + } + // Constructor copying CUs from input container. template inline compile_units (const input &other, tracker &t) : dwarf_data::compile_units (other, t) {} - inline compile_units (const compile_units &) - : dwarf_data::compile_units () - { - throw std::logic_error - ("must copy-construct top-level dwarf_output object instead"); - } - public: // Default constructor: an empty container, no CUs. inline compile_units () {} @@ -715,9 +589,12 @@ namespace elfutils to_string (const dwarf_output::attribute &); template<> std::string - to_string (const dwarf_output::attr_value&); + to_string (const dwarf_output::attr_value &); -#endif + inline std::string dwarf_output::attr_value::to_string () const + { + return elfutils::to_string (*this); // Use that. + } class dwarf_output_collector { @@ -727,9 +604,11 @@ namespace elfutils dwarf_path_finder _m_tracker; typedef dwarf_output::debug_info_entry die_type; - typedef die_type::children_type::const_iterator die_ptr; typedef die_type::attributes_type attrs_type; + typedef die_type::children_type children_type; + typedef children_type::const_iterator die_ptr; + // Simple value sets for leaf types. subr::value_set _m_strings; subr::value_set _m_identifiers; subr::value_set _m_address; @@ -743,6 +622,7 @@ namespace elfutils subr::value_set _m_source_column; subr::value_set _m_locations; + // The set of Boolean flags is a doubleton. static const dwarf_output::value::value_flag flag_true; static const dwarf_output::value::value_flag flag_false; static inline const dwarf_output::value::value_flag *flag (bool flag) @@ -750,18 +630,8 @@ namespace elfutils return flag ? &flag_true : &flag_false; } - struct same_attrs : public std::equal_to - { - bool operator () (const die_type::attributes_type &a, - const die_type::attributes_type &b) const - { - return a.are (b); - } - }; - - typedef std::tr1::unordered_set attrs_set; - attrs_set _m_attr_sets; + // Set of attribute maps. + subr::identity_set _m_attr_sets; template inline const attrs_type *add_attributes (const input &x, copier_type &c) @@ -769,6 +639,45 @@ namespace elfutils return &*_m_attr_sets.insert (attrs_type (x, c)).first; } + // Set of children lists. + subr::identity_set _m_broods; + + template + inline const children_type *add_children (const input &x, copier_type &c) + { + return &*_m_broods.insert (children_type (x, c)).first; + } + + struct die_info + { + unsigned int uses; + bool with_sibling; + bool without_sibling; + + inline die_info () + : uses (0), with_sibling (false), without_sibling (false) + {} + }; + + // Set of unique DIEs. + typedef subr::identity_map die_map; + die_map _m_unique; + + template + inline const die_type *add_entry (const input &other, copier_type &c, + bool has_sibling) + { + typename die_map::value_type &x + = *_m_unique.insert (std::make_pair (die_type (other, c), + die_info ())).first; + x.second.uses++; + if (has_sibling) + x.second.with_sibling = true; + else + x.second.without_sibling = true; + return &x.first; + } + struct shape_type { typedef std::vector > attrs_type; @@ -951,12 +860,26 @@ namespace elfutils return _m_collector->add_attributes (x, *this); } + template + inline const debug_info_entry::children_type * + add_children (const input &x) + { + return _m_collector->add_children (x, *this); + } + + template + inline const debug_info_entry * + add_entry (const input &x, bool has_sibling) + { + return _m_collector->add_entry (x, *this, has_sibling); + } + template inline void copied (const debug_info_entry::children_type::iterator &out, - const input_iter &in, bool last_sibling) + const input_iter &in, bool /*has_sibling*/) { equivalence (out, in); - _m_collector->add_shape (*out, last_sibling); + // XXX _m_collector->add_shape (*out, !has_sibling); } }; }; diff --git a/libdw/c++/edit-values.cc b/libdw/c++/edit-values.cc index d1b441670..03c157439 100644 --- a/libdw/c++/edit-values.cc +++ b/libdw/c++/edit-values.cc @@ -59,10 +59,7 @@ template<> std::string to_string (const dwarf_edit::attribute &attr) { - std::string result = dwarf::attributes::name (attr.first); - result += "="; - result += attr.second.to_string (); - return result; + return attribute_string (attr); } std::string diff --git a/libdw/c++/output-values.cc b/libdw/c++/output-values.cc index 86b7e1f3a..07212134c 100644 --- a/libdw/c++/output-values.cc +++ b/libdw/c++/output-values.cc @@ -61,10 +61,7 @@ template<> std::string to_string (const dwarf_output::attribute &attr) { - std::string result = dwarf::attributes::name (attr.first); - result += "="; - result += attr.second.to_string (); - return result; + return attribute_string (attr); } const dwarf_output::value::value_flag dwarf_output_collector::flag_true (1); diff --git a/libdw/c++/subr.hh b/libdw/c++/subr.hh index 1ad1a52de..ca6a709e5 100644 --- a/libdw/c++/subr.hh +++ b/libdw/c++/subr.hh @@ -631,6 +631,10 @@ namespace elfutils public: typedef element value_type; + inline wrapped_input_iterator () + : _base () + {} + template inline wrapped_input_iterator (const _base &i, const arg_type &arg) : _base (static_cast<_base> (i)), _m_wrapper (arg) @@ -644,6 +648,30 @@ namespace elfutils { return _m_wrapper (_base::operator* ()); } + + inline element *operator-> () const + { + return &(_m_wrapper (_base::operator* ())); + } + + inline wrapped_input_iterator &operator++ () // prefix + { + _base::operator++ (); + return *this; + } + inline wrapped_input_iterator operator++ (int magic) // postfix + { + return wrapped_input_iterator (_base::operator++ (magic)); + } + inline wrapped_input_iterator &operator-- () // prefix + { + _base::operator-- (); + return *this; + } + inline wrapped_input_iterator operator-- (int magic) // postfix + { + return wrapped_input_iterator (_base::operator-- (magic)); + } }; /* An iterator adapter for use in iterator-based constructors. @@ -855,6 +883,28 @@ namespace elfutils } } }; + + template + struct is : public std::equal_to + { + bool operator () (const T &a, const T &b) const + { + return a.is (b); + } + }; + + template + struct identity_set + : public std::tr1::unordered_set > + {}; + + template + struct identity_map + : public std::tr1::unordered_map > + {}; + }; }; diff --git a/libdw/c++/values.cc b/libdw/c++/values.cc index bdac9a281..ccfbd574f 100644 --- a/libdw/c++/values.cc +++ b/libdw/c++/values.cc @@ -52,6 +52,7 @@ #include "dwarf" #include "dwarf_edit" #include "dwarf_output" +#include "data-values.hh" extern "C" { @@ -237,10 +238,7 @@ template<> string to_string (const dwarf::attribute &attr) { - std::string result = dwarf::attributes::name (attr.first); - result += "="; - result += attr.second.to_string (); - return result; + return attribute_string (attr); } template<>