summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2009-07-07 03:34:59 -0700
committerRoland McGrath <roland@redhat.com>2009-07-07 03:34:59 -0700
commit2c1901ebaf4862da6e9fb9b1d60f0b5f8ac7dcbc (patch)
treedbee807691feed3e24b4d82370f1f1b9f644ab49
parentd0084a295377e0bed6df39bb2bc3997347ea46d7 (diff)
downloadelfutils-roland/dwarf_output-shape.tar.gz
-rw-r--r--libdw/c++/dwarf_output97
-rw-r--r--libdw/c++/subr.hh62
2 files changed, 118 insertions, 41 deletions
diff --git a/libdw/c++/dwarf_output b/libdw/c++/dwarf_output
index 3d8ea2eb..d0dcd518 100644
--- a/libdw/c++/dwarf_output
+++ b/libdw/c++/dwarf_output
@@ -488,10 +488,19 @@ namespace elfutils
t.equivalence (out, in);
}
- template<typename input, typename tracker>
- inline children_type (const input &other, tracker &t)
+ template<typename input_dw>
+ static inline void
+ add_shape (const iterator &out, bool no_sibling, copier<input_dw> &c)
+ {
+ c.add_shape (*out, no_sibling);
+ }
+
+ template<typename input, typename input_dw>
+ inline children_type (const input &other, copier<input_dw> &c)
{
- subr::create_container (this, other, t, equivalence<input, tracker>);
+ subr::create_container (this, other, c,
+ equivalence<input, copier<input_dw> >,
+ add_shape<input_dw>);
}
public:
@@ -760,16 +769,27 @@ template<typename flavor>
return flag ? &flag_true : &flag_false;
}
- struct same_attrs : public std::equal_to<die_type::attributes_type>
+ class shape;
+
+ struct attrs_shape : public attrs_type
+ {
+ shape *_m_shape;
+
+ template<typename input, typename copier_type>
+ inline attrs_shape (const input &x, copier_type &c)
+ : attrs_type (x, c), _m_shape (NULL)
+ {}
+ };
+
+ struct same_attrs : public std::equal_to<attrs_type>
{
- bool operator () (const die_type::attributes_type &a,
- const die_type::attributes_type &b) const
+ bool operator () (const attrs_shape &a, const attrs_shape &b) const
{
return a.are (b);
}
};
- typedef std::tr1::unordered_set<attrs_type, attrs_type::hasher,
+ typedef std::tr1::unordered_set<attrs_shape, attrs_shape::hasher,
same_attrs> attrs_set;
attrs_set _m_attr_sets;
@@ -777,12 +797,59 @@ template<typename flavor>
inline const attrs_type *add_attributes (const input &x, copier_type &c)
{
std::pair<attrs_set::iterator, bool> p
- = _m_attr_sets.insert (attrs_type (x, c));
- if (p.second)
+ = _m_attr_sets.insert (attrs_shape (x, c));
+ assert (p.second == (p.first->_m_shape == NULL));
+ return &*p.first;
+ }
+
+ typedef subr::container_hasher<std::map<int, int> > map_hasher;
+
+ struct shape
+ : public subr::hashed_value<std::map<int, int>, map_hasher>
+ {
+ typedef subr::hashed_value<std::map<int, int>, map_hasher> _base;
+ typedef _base::value_type::value_type shape_pair;
+
+ enum context
{
- // XXX hook for collection: abbrev building, etc.
+ no_children_no_sibling,
+ no_children_has_sibling,
+ has_children_no_sibling,
+ has_children_has_sibling,
+ shape_context_bits
+ };
+ std::bitset<shape_context_bits> _m_used;
+
+ struct make_shape_pair
+ : public std::unary_function<attrs_type::value_type, shape_pair>
+ {
+ inline shape_pair operator () (const attrs_type::value_type &attr) const
+ {
+ return shape_pair (attr.first,
+ (int) DW_FORM_indirect); // XXX
}
- return &(*p.first);
+ };
+
+ typedef subr::wrapped_input_iterator<attrs_type, make_shape_pair> maker;
+
+ inline shape (const attrs_type &attrs)
+ : _base (maker (attrs.begin ()), maker (attrs.end ())), _m_used ()
+ {}
+
+ inline void user (bool has_children, bool has_sibling)
+ {
+ _m_used.set (has_children * 2 + has_sibling);
+ }
+ };
+
+ subr::value_set<shape> _m_shapes;
+
+ inline void add_shape (const die_type &die, bool no_sibling)
+ {
+ const attrs_shape &attrs = const_cast<attrs_shape &>
+ (static_cast<const attrs_shape &> (die.attributes ()));
+ assert (attrs._m_shape == NULL && (no_sibling || !no_sibling));
+ // XXX hook for collection: abbrev building, etc.
}
};
@@ -904,7 +971,13 @@ template<typename flavor>
{
return _m_collector->add_attributes (x, *this);
}
- };
+
+ inline void add_shape (const dwarf_output::debug_info_entry &die,
+ bool no_sibling)
+ {
+ _m_collector->add_shape (die, no_sibling);
+ }
+ };
// Copy construction instantiates a copier derived from the collector.
template<typename input>
diff --git a/libdw/c++/subr.hh b/libdw/c++/subr.hh
index 8d42a77e..1df1744a 100644
--- a/libdw/c++/subr.hh
+++ b/libdw/c++/subr.hh
@@ -387,33 +387,29 @@ namespace elfutils
};
// Pair of some value and its precomputed hash.
- template<typename T>
- class hashed_value
- : public std::pair<size_t, const T>
+ template<typename T, typename value_hasher = subr::hash<T> >
+ struct hashed_value
{
- private:
- typedef std::pair<size_t, const T> _base;
-
- public:
typedef T value_type;
- struct hasher
- : public std::unary_function<hashed_value, size_t>
- {
- inline size_t operator () (const hashed_value &v) const
- {
- return v.first;
- }
- };
+ const T _m_value;
+ size_t _m_hash;
+
+ friend class hashed_hasher<hashed_value>;
+ typedef hashed_hasher<hashed_value> hasher;
- hashed_value (const value_type &v)
- : _base (hash_this (v), v) {}
- hashed_value (const hashed_value &v)
- : _base (v.first, v.second) {}
+ inline hashed_value (const hashed_value &v)
+ : _m_value (v._m_value), _m_hash (v._m_hash)
+ {}
+
+ template<typename... argtypes>
+ inline hashed_value (argtypes&&...args)
+ : _m_value (args...), _m_hash (value_hasher () (_m_value))
+ {}
bool operator== (const hashed_value &other) const
{
- return other.first == this->first && other.second == this->second;
+ return other._m_hash == _m_hash && other._m_value == _m_value;
}
};
@@ -439,7 +435,7 @@ namespace elfutils
{
// XXX hook for collection: abbrev building, etc.
}
- return &p.first->second;
+ return &p.first->_m_value;
};
template<typename input>
@@ -628,9 +624,9 @@ namespace elfutils
public:
typedef element value_type;
- template<typename arg_type>
- inline wrapped_input_iterator (const _base &i, const arg_type &arg)
- : _base (static_cast<_base> (i)), _m_wrapper (arg)
+ template<typename... argtypes>
+ inline wrapped_input_iterator (const _base &i, argtypes&&...args)
+ : _base (static_cast<_base> (i)), _m_wrapper (args...)
{}
inline wrapped_input_iterator (const wrapped_input_iterator &i)
@@ -833,13 +829,18 @@ namespace elfutils
struct create_container
{
template<typename container, typename input, typename arg_type,
- typename hook_type = const nothing>
+ typename hook_type = const nothing,
+ typename hook2_type = const nothing>
inline create_container (container *me, const input &other,
- arg_type &arg, hook_type &hook = hook_type ())
+ arg_type &arg,
+ hook_type &hook = hook_type (),
+ hook2_type &hook2 = hook2_type ())
{
- for (typename input::const_iterator in = other.begin ();
- in != other.end ();
- ++in)
+ typename input::const_iterator in = other.begin ();
+ if (in == other.end ())
+ return;
+ bool last;
+ do
{
/* Don't copy-construct the entry from *in here because that
copies it again into the list and destroys the first copy. */
@@ -847,7 +848,10 @@ namespace elfutils
typename container::iterator out = --me->end ();
out->set (*in, arg);
hook (out, in, arg);
+ last = ++in == other.end ();
+ hook2 (out, last, arg);
}
+ while (!last);
}
};
};