From 28942d3ba886b4f215ac6ddaa05c55d35d927621 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 12 Jul 2017 01:34:21 +0000 Subject: Remove dependancy on __refstring header; use local copy instead. This patch removes the dependancy on libc++'s __refstring header, which was only a header in the first place so that libc++abi could build library code using it, and not because libc++ needed it in the headers. This patch allows libc++ to stop shipping <__refstring> publicaly at the cost of duplicating it across projects. Ideally libc++abi would always require the libc++ sources when building, but that's a separate discussion I plan to start on the mailing lists shortly. git-svn-id: https://llvm.org/svn/llvm-project/libcxxabi/trunk@307748 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/include/refstring.h | 131 +++++++++++++++++++++++++++++++++++++++++++++++ src/stdlib_stdexcept.cpp | 2 +- 2 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 src/include/refstring.h diff --git a/src/include/refstring.h b/src/include/refstring.h new file mode 100644 index 0000000..bc131ae --- /dev/null +++ b/src/include/refstring.h @@ -0,0 +1,131 @@ +//===------------------------ __refstring ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// FIXME: This file is copied from libcxx/src/include/refstring.h. Instead of +// duplicating the file in libc++abi we should require that the libc++ sources +// are available when building libc++abi. + +#ifndef _LIBCPPABI_REFSTRING_H +#define _LIBCPPABI_REFSTRING_H + +#include <__config> +#include +#include +#include +#ifdef __APPLE__ +#include +#include +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __refstring_imp { namespace { +typedef int count_t; + +struct _Rep_base { + std::size_t len; + std::size_t cap; + count_t count; +}; + +inline _Rep_base* rep_from_data(const char *data_) noexcept { + char *data = const_cast(data_); + return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); +} + +inline char * data_from_rep(_Rep_base *rep) noexcept { + char *data = reinterpret_cast(rep); + return data + sizeof(*rep); +} + +#if defined(__APPLE__) +inline +const char* compute_gcc_empty_string_storage() _NOEXCEPT +{ + void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); + if (handle == nullptr) + return nullptr; + void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); + if (sym == nullptr) + return nullptr; + return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); +} + +inline +const char* +get_gcc_empty_string_storage() _NOEXCEPT +{ + static const char* p = compute_gcc_empty_string_storage(); + return p; +} +#endif + +}} // namespace __refstring_imp + +using namespace __refstring_imp; + +inline +__libcpp_refstring::__libcpp_refstring(const char* msg) { + std::size_t len = strlen(msg); + _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); + rep->len = len; + rep->cap = len; + rep->count = 0; + char *data = data_from_rep(rep); + std::memcpy(data, msg, len + 1); + __imp_ = data; +} + +inline +__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT + : __imp_(s.__imp_) +{ + if (__uses_refcount()) + __sync_add_and_fetch(&rep_from_data(__imp_)->count, 1); +} + +inline +__libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT { + bool adjust_old_count = __uses_refcount(); + struct _Rep_base *old_rep = rep_from_data(__imp_); + __imp_ = s.__imp_; + if (__uses_refcount()) + __sync_add_and_fetch(&rep_from_data(__imp_)->count, 1); + if (adjust_old_count) + { + if (__sync_add_and_fetch(&old_rep->count, count_t(-1)) < 0) + { + ::operator delete(old_rep); + } + } + return *this; +} + +inline +__libcpp_refstring::~__libcpp_refstring() { + if (__uses_refcount()) { + _Rep_base* rep = rep_from_data(__imp_); + if (__sync_add_and_fetch(&rep->count, count_t(-1)) < 0) { + ::operator delete(rep); + } + } +} + +inline +bool __libcpp_refstring::__uses_refcount() const { +#ifdef __APPLE__ + return __imp_ != get_gcc_empty_string_storage(); +#else + return true; +#endif +} + +_LIBCPP_END_NAMESPACE_STD + +#endif //_LIBCPPABI_REFSTRING_H diff --git a/src/stdlib_stdexcept.cpp b/src/stdlib_stdexcept.cpp index bd6789e..e3b7cd4 100644 --- a/src/stdlib_stdexcept.cpp +++ b/src/stdlib_stdexcept.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "__refstring" +#include "include/refstring.h" #include "stdexcept" #include "new" #include -- cgit v1.2.3