From f41fced0fc3d91c92495af7504b0804db2b0dde7 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Mon, 5 Oct 2009 21:34:45 +0200 Subject: [PATCH] dwarflint: C++ify coverage analysis * only the implementation so far, we need the interface intact until dwarflint low-level is in C --- ...flint-coverage.c => dwarflint-coverage.cc} | 101 ++++++++++-------- src/dwarflint-coverage.h | 14 ++- src/dwarflint-coverage.hh | 95 ++++++++++++++++ 3 files changed, 162 insertions(+), 48 deletions(-) rename src/{dwarflint-coverage.c => dwarflint-coverage.cc} (83%) create mode 100644 src/dwarflint-coverage.hh diff --git a/src/dwarflint-coverage.c b/src/dwarflint-coverage.cc similarity index 83% rename from src/dwarflint-coverage.c rename to src/dwarflint-coverage.cc index 1bec5549a..aa9b17c3f 100644 --- a/src/dwarflint-coverage.c +++ b/src/dwarflint-coverage.cc @@ -1,4 +1,4 @@ -/* Coverage analysis. +/* Implementation of coverage analysis. Copyright (C) 2008,2009 Red Hat, Inc. This file is part of Red Hat elfutils. @@ -28,35 +28,44 @@ # include #endif -#include "dwarflint-coverage.h" +#include "dwarflint-coverage.hh" +extern "C" +{ +#include "../lib/system.h" +} + #include #include -#include #include #include -static size_t -coverage_find (struct coverage const *cov, uint64_t start) + +namespace { - assert (cov->size > 0); + template + decltype (((X *)0)->ranges) + coverage_find (X *cov, uint64_t start) + { + assert (cov->size > 0); - size_t a = 0; - size_t b = cov->size; + size_t a = 0; + size_t b = cov->size; - while (a < b) - { - size_t i = (a + b) / 2; - struct cov_range const *r = cov->ranges + i; + while (a < b) + { + size_t i = (a + b) / 2; + cov_range const *r = cov->ranges + i; - if (r->start > start) - b = i; - else if (r->start < start) - a = i + 1; - else - return i; - } + if (r->start > start) + b = i; + else if (r->start < start) + a = i + 1; + else + return cov->ranges + i; + } - return a; + return cov->ranges + a; + } } void @@ -73,7 +82,7 @@ coverage_add (struct coverage *cov, uint64_t start, uint64_t length) return; } - struct cov_range *r = cov->ranges + coverage_find (cov, start); + struct cov_range *r = coverage_find (cov, start); struct cov_range *insert = &nr; struct cov_range *coalesce = &nr; @@ -142,7 +151,7 @@ coverage_remove (struct coverage *cov, uint64_t begin, uint64_t length) if (cov->size == 0 || begin == end) return false; - struct cov_range *r = cov->ranges + coverage_find (cov, begin); + struct cov_range *r = coverage_find (cov, begin); struct cov_range *erase_begin = NULL, *erase_end = r; // end exclusive bool overlap = false; @@ -214,7 +223,7 @@ coverage_is_covered (struct coverage const *cov, if (cov->size == 0) return false; - struct cov_range const *r = cov->ranges + coverage_find (cov, start); + struct cov_range const *r = coverage_find (cov, start); uint64_t end = start + length; if (r < cov->ranges + cov->size) if (start >= r->start) @@ -229,6 +238,17 @@ coverage_is_covered (struct coverage const *cov, return false; } +namespace +{ + bool overlaps (uint64_t start, uint64_t end, + struct cov_range const *r) + { + return (start >= r->start && start < r->start + r->length) + || (end > r->start && end <= r->start + r->length) + || (start < r->start && end > r->start + r->length); + } +} + bool coverage_is_overlap (struct coverage const *cov, uint64_t start, uint64_t length) @@ -237,20 +257,14 @@ coverage_is_overlap (struct coverage const *cov, return false; uint64_t end = start + length; - bool overlaps (struct cov_range const *r) - { - return (start >= r->start && start < r->start + r->length) - || (end > r->start && end <= r->start + r->length) - || (start < r->start && end > r->start + r->length); - } - struct cov_range const *r = cov->ranges + coverage_find (cov, start); + struct cov_range const *r = coverage_find (cov, start); - if (r < cov->ranges + cov->size && overlaps (r)) + if (r < cov->ranges + cov->size && overlaps (start, end, r)) return true; if (r > cov->ranges) - return overlaps (r - 1); + return overlaps (start, end, r - 1); return false; } @@ -267,25 +281,20 @@ coverage_find_holes (struct coverage const *cov, if (cov->size == 0) return hole (start, length, data); - uint64_t end (size_t i) - { - return cov->ranges[i].start + cov->ranges[i].length; - } - if (start < cov->ranges[0].start) if (!hole (start, cov->ranges[0].start - start, data)) return false; for (size_t i = 0; i < cov->size - 1; ++i) { - uint64_t end_i = end (i); + uint64_t end_i = cov->ranges[i].end (); if (!hole (end_i, cov->ranges[i+1].start - end_i, data)) return false; } - if (start + length > end (cov->size - 1)) + if (start + length > cov->back ().end ()) { - uint64_t end_last = end (cov->size - 1); + uint64_t end_last = cov->back ().end (); return hole (end_last, start + length - end_last, data); } @@ -310,26 +319,26 @@ coverage_free (struct coverage *cov) free (cov->ranges); } -struct coverage * +coverage * coverage_clone (struct coverage const *cov) { - struct coverage *ret = xmalloc (sizeof (*ret)); + coverage *ret = (coverage *)xmalloc (sizeof (*ret)); WIPE (*ret); coverage_add_all (ret, cov); return ret; } void -coverage_add_all (struct coverage *restrict cov, - struct coverage const *restrict other) +coverage_add_all (struct coverage *__restrict__ cov, + struct coverage const *__restrict__ other) { for (size_t i = 0; i < other->size; ++i) coverage_add (cov, other->ranges[i].start, other->ranges[i].length); } bool -coverage_remove_all (struct coverage *restrict cov, - struct coverage const *restrict other) +coverage_remove_all (struct coverage *__restrict__ cov, + struct coverage const *__restrict__ other) { bool ret = false; for (size_t i = 0; i < other->size; ++i) diff --git a/src/dwarflint-coverage.h b/src/dwarflint-coverage.h index 26b732771..ed4f00fe8 100644 --- a/src/dwarflint-coverage.h +++ b/src/dwarflint-coverage.h @@ -41,8 +41,9 @@ _a->alloc = 8; \ else \ _a->alloc *= 2; \ - _a->BUF = xrealloc (_a->BUF, \ - sizeof (*_a->BUF) * _a->alloc); \ + _a->BUF = (typeof (_a->BUF)) \ + xrealloc (_a->BUF, \ + sizeof (*_a->BUF) * _a->alloc); \ } \ } while (0) @@ -62,6 +63,10 @@ struct cov_range { uint64_t start; uint64_t length; + +#ifdef __cplusplus + uint64_t end () const { return start + length; } +#endif }; struct coverage @@ -69,6 +74,11 @@ struct coverage struct cov_range *ranges; size_t size; size_t alloc; + +#ifdef __cplusplus + cov_range &back () { return ranges[size - 1]; } + cov_range const &back () const { return ranges[size - 1]; } +#endif }; struct coverage *coverage_clone (struct coverage const *cov) diff --git a/src/dwarflint-coverage.hh b/src/dwarflint-coverage.hh new file mode 100644 index 000000000..ec3a68113 --- /dev/null +++ b/src/dwarflint-coverage.hh @@ -0,0 +1,95 @@ +/* Coverage analysis, C++ support. + + Copyright (C) 2008,2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils 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; version 2 of the License. + + Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + . */ + +#ifndef DWARFLINT_COVERAGE_HH +#define DWARFLINT_COVERAGE_HH + +#include +#include +#include "dwarflint-coverage.h" + +namespace cov +{ + class _format_base + { + protected: + std::string const &_m_delim; + std::ostringstream _m_os; + bool _m_seen; + + inline bool fmt (uint64_t start, uint64_t length) + { + if (_m_seen) + _m_os << _m_delim; + _m_os << "[" << start << ", " << start + length << ")"; + _m_seen = true; + return true; + } + + static bool + wrap_fmt (uint64_t start, uint64_t length, void *data) + { + _format_base *self = static_cast <_format_base *> (data); + return self->fmt (start, length); + } + + _format_base (std::string const &delim) + : _m_delim (delim), + _m_seen (false) + { + _m_os << std::hex; + } + + public: + operator std::string () + { + return _m_os.str (); + } + }; + + struct format_ranges + : public _format_base + { + format_ranges (coverage const &cov, std::string const &delim = ", ") + : _format_base (delim) + { + coverage_find_ranges (&cov, &wrap_fmt, this); + } + }; + + struct format_holes + : public _format_base + { + format_holes (coverage const &cov, uint64_t start, uint64_t length, + std::string const &delim = ", ") + : _format_base (delim) + { + coverage_find_holes (&cov, start, length, &wrap_fmt, this); + } + }; +} + +#endif//DWARFLINT_COVERAGE_HH -- 2.47.3