Commit 38bf94280b
Changed files (11)
lib/libcxxabi/include/__cxxabi_config.h
@@ -18,6 +18,19 @@
#define __has_attribute(_attribute_) 0
#endif
+#if defined(__clang__)
+# define _LIBCXXABI_COMPILER_CLANG
+# ifndef __apple_build_version__
+# define _LIBCXXABI_CLANG_VER (__clang_major__ * 100 + __clang_minor__)
+# endif
+#elif defined(__GNUC__)
+# define _LIBCXXABI_COMPILER_GCC
+#elif defined(_MSC_VER)
+# define _LIBCXXABI_COMPILER_MSVC
+#elif defined(__IBMCPP__)
+# define _LIBCXXABI_COMPILER_IBM
+#endif
+
#if defined(_WIN32)
#if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS)
#define _LIBCXXABI_HIDDEN
@@ -53,7 +66,7 @@
#endif
#endif
-#if defined(_WIN32)
+#if defined(_LIBCXXABI_COMPILER_MSVC)
#define _LIBCXXABI_WEAK
#else
#define _LIBCXXABI_WEAK __attribute__((__weak__))
@@ -72,7 +85,7 @@
#endif
// wasm32 follows the arm32 ABI convention of using 32-bit guard.
-#if defined(__arm__) || defined(__wasm32__)
+#if defined(__arm__) || defined(__wasm32__) || defined(__ARM64_ARCH_8_32__)
# define _LIBCXXABI_GUARD_ABI_ARM
#endif
lib/libcxxabi/include/cxxabi.h
@@ -21,6 +21,7 @@
#define _LIBCPPABI_VERSION 1002
#define _LIBCXXABI_NORETURN __attribute__((noreturn))
+#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold))
#ifdef __cplusplus
@@ -78,13 +79,13 @@ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_deleted_virtual(void);
// 3.3.2 One-time Construction API
#if defined(_LIBCXXABI_GUARD_ABI_ARM)
-extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint32_t *);
-extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint32_t *);
-extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint32_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t *);
#else
-extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint64_t *);
-extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint64_t *);
-extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint64_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t *);
#endif
// 3.3.3 Array Construction and Destruction API
@@ -136,9 +137,9 @@ __cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count,
void (*destructor)(void *));
// 3.3.5.3 Runtime API
-extern _LIBCXXABI_FUNC_VIS int __cxa_atexit(void (*f)(void *), void *p,
- void *d);
-extern _LIBCXXABI_FUNC_VIS int __cxa_finalize(void *);
+// These functions are part of the C++ ABI, but they are not defined in libc++abi:
+// int __cxa_atexit(void (*)(void *), void *, void *);
+// void __cxa_finalize(void *);
// 3.4 Demangler API
extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name,
lib/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -82,6 +82,7 @@
X(PostfixExpr) \
X(ConditionalExpr) \
X(MemberExpr) \
+ X(SubobjectExpr) \
X(EnclosingExpr) \
X(CastExpr) \
X(SizeofParamPackExpr) \
@@ -91,6 +92,7 @@
X(PrefixExpr) \
X(FunctionParam) \
X(ConversionExpr) \
+ X(PointerToMemberConversionExpr) \
X(InitListExpr) \
X(FoldExpr) \
X(ThrowExpr) \
@@ -1656,6 +1658,40 @@ public:
}
};
+class SubobjectExpr : public Node {
+ const Node *Type;
+ const Node *SubExpr;
+ StringView Offset;
+ NodeArray UnionSelectors;
+ bool OnePastTheEnd;
+
+public:
+ SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
+ NodeArray UnionSelectors_, bool OnePastTheEnd_)
+ : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
+ UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
+
+ template<typename Fn> void match(Fn F) const {
+ F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
+ }
+
+ void printLeft(OutputStream &S) const override {
+ SubExpr->print(S);
+ S += ".<";
+ Type->print(S);
+ S += " at offset ";
+ if (Offset.empty()) {
+ S += "0";
+ } else if (Offset[0] == 'n') {
+ S += "-";
+ S += Offset.dropFront();
+ } else {
+ S += Offset;
+ }
+ S += ">";
+ }
+};
+
class EnclosingExpr : public Node {
const StringView Prefix;
const Node *Infix;
@@ -1843,6 +1879,28 @@ public:
}
};
+class PointerToMemberConversionExpr : public Node {
+ const Node *Type;
+ const Node *SubExpr;
+ StringView Offset;
+
+public:
+ PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
+ StringView Offset_)
+ : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_),
+ Offset(Offset_) {}
+
+ template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); }
+
+ void printLeft(OutputStream &S) const override {
+ S += "(";
+ Type->print(S);
+ S += ")(";
+ SubExpr->print(S);
+ S += ")";
+ }
+};
+
class InitListExpr : public Node {
const Node *Ty;
NodeArray Inits;
@@ -2313,9 +2371,9 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
TemplateParamList Params;
public:
- ScopedTemplateParamList(AbstractManglingParser *Parser)
- : Parser(Parser),
- OldNumTemplateParamLists(Parser->TemplateParams.size()) {
+ ScopedTemplateParamList(AbstractManglingParser *TheParser)
+ : Parser(TheParser),
+ OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Parser->TemplateParams.push_back(&Params);
}
~ScopedTemplateParamList() {
@@ -2437,6 +2495,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Node *parseConversionExpr();
Node *parseBracedExpr();
Node *parseFoldExpr();
+ Node *parsePointerToMemberConversionExpr();
+ Node *parseSubobjectExpr();
/// Parse the <type> production.
Node *parseType();
@@ -4404,6 +4464,50 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);
}
+// <expression> ::= mc <parameter type> <expr> [<offset number>] E
+//
+// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr() {
+ Node *Ty = getDerived().parseType();
+ if (!Ty)
+ return nullptr;
+ Node *Expr = getDerived().parseExpr();
+ if (!Expr)
+ return nullptr;
+ StringView Offset = getDerived().parseNumber(true);
+ if (!consumeIf('E'))
+ return nullptr;
+ return make<PointerToMemberConversionExpr>(Ty, Expr, Offset);
+}
+
+// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
+// <union-selector> ::= _ [<number>]
+//
+// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
+ Node *Ty = getDerived().parseType();
+ if (!Ty)
+ return nullptr;
+ Node *Expr = getDerived().parseExpr();
+ if (!Expr)
+ return nullptr;
+ StringView Offset = getDerived().parseNumber(true);
+ size_t SelectorsBegin = Names.size();
+ while (consumeIf('_')) {
+ Node *Selector = make<NameType>(parseNumber());
+ if (!Selector)
+ return nullptr;
+ Names.push_back(Selector);
+ }
+ bool OnePastTheEnd = consumeIf('p');
+ if (!consumeIf('E'))
+ return nullptr;
+ return make<SubobjectExpr>(
+ Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
+}
+
// <expression> ::= <unary operator-name> <expression>
// ::= <binary operator-name> <expression> <expression>
// ::= <ternary operator-name> <expression> <expression> <expression>
@@ -4661,6 +4765,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
return nullptr;
case 'm':
switch (First[1]) {
+ case 'c':
+ First += 2;
+ return parsePointerToMemberConversionExpr();
case 'i':
First += 2;
return getDerived().parseBinaryExpr("-");
@@ -4808,6 +4915,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
return Ex;
return make<CastExpr>("static_cast", T, Ex);
}
+ case 'o':
+ First += 2;
+ return parseSubobjectExpr();
case 'p': {
First += 2;
Node *Child = getDerived().parseExpr();
@@ -4975,6 +5085,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
switch (look()) {
case 'T':
switch (look(1)) {
+ // TA <template-arg> # template parameter object
+ //
+ // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
+ case 'A': {
+ First += 2;
+ Node *Arg = getDerived().parseTemplateArg();
+ if (Arg == nullptr)
+ return nullptr;
+ return make<SpecialName>("template parameter object for ", Arg);
+ }
// TV <type> # virtual table
case 'V': {
First += 2;
@@ -5103,7 +5223,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
decltype(TemplateParams) OldParams;
public:
- SaveTemplateParams(AbstractManglingParser *Parser) : Parser(Parser) {
+ SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
OldParams = std::move(Parser->TemplateParams);
Parser->TemplateParams.clear();
}
@@ -5203,7 +5323,12 @@ struct FloatData<long double>
#else
static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
#endif
- static const size_t max_demangled_size = 40;
+ // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
+ // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
+ // Negatives are one character longer than positives.
+ // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
+ // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
+ static const size_t max_demangled_size = 42;
static constexpr const char *spec = "%LaL";
};
lib/libcxxabi/src/demangle/Utility.h
@@ -52,7 +52,7 @@ class OutputStream {
char *TempPtr = std::end(Temp);
while (N) {
- *--TempPtr = '0' + char(N % 10);
+ *--TempPtr = char('0' + N % 10);
N /= 10;
}
lib/libcxxabi/src/include/refstring.h
@@ -1,131 +0,0 @@
-//===------------------------ __refstring ---------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// 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 <stdexcept>
-#include <cstddef>
-#include <cstring>
-#ifdef __APPLE__
-#include <dlfcn.h>
-#include <mach-o/dyld.h>
-#endif
-#include "atomic_support.h"
-
-_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<char *>(data_);
- return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base));
-}
-
-inline char * data_from_rep(_Rep_base *rep) noexcept {
- char *data = reinterpret_cast<char *>(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())
- __libcpp_atomic_add(&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())
- __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1);
- if (adjust_old_count)
- {
- if (__libcpp_atomic_add(&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 (__libcpp_atomic_add(&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
lib/libcxxabi/src/cxa_guard_impl.h
@@ -54,6 +54,14 @@
#endif
#endif
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wtautological-pointer-compare"
+#elif defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Waddress"
+#endif
+
// To make testing possible, this header is included from both cxa_guard.cpp
// and a number of tests.
//
@@ -112,25 +120,25 @@ class AtomicInt {
public:
using MemoryOrder = std::__libcpp_atomic_order;
- explicit AtomicInt(IntType *b) : b(b) {}
+ explicit AtomicInt(IntType *b) : b_(b) {}
AtomicInt(AtomicInt const&) = delete;
AtomicInt& operator=(AtomicInt const&) = delete;
IntType load(MemoryOrder ord) {
- return std::__libcpp_atomic_load(b, ord);
+ return std::__libcpp_atomic_load(b_, ord);
}
void store(IntType val, MemoryOrder ord) {
- std::__libcpp_atomic_store(b, val, ord);
+ std::__libcpp_atomic_store(b_, val, ord);
}
IntType exchange(IntType new_val, MemoryOrder ord) {
- return std::__libcpp_atomic_exchange(b, new_val, ord);
+ return std::__libcpp_atomic_exchange(b_, new_val, ord);
}
bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
- return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure);
+ return std::__libcpp_atomic_compare_exchange(b_, expected, desired, ord_success, ord_failure);
}
private:
- IntType *b;
+ IntType *b_;
};
//===----------------------------------------------------------------------===//
@@ -154,14 +162,7 @@ constexpr uint32_t (*PlatformThreadID)() = nullptr;
constexpr bool PlatformSupportsThreadID() {
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
-#endif
return +PlatformThreadID != nullptr;
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
}
//===----------------------------------------------------------------------===//
@@ -375,18 +376,18 @@ private:
LockGuard& operator=(LockGuard const&) = delete;
explicit LockGuard(const char* calling_func)
- : calling_func(calling_func) {
+ : calling_func_(calling_func) {
if (global_mutex.lock())
- ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func);
+ ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func_);
}
~LockGuard() {
if (global_mutex.unlock())
- ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func);
+ ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func_);
}
private:
- const char* const calling_func;
+ const char* const calling_func_;
};
};
@@ -411,14 +412,7 @@ constexpr void (*PlatformFutexWake)(int*) = nullptr;
#endif
constexpr bool PlatformSupportsFutex() {
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
-#endif
return +PlatformFutexWait != nullptr;
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
}
/// InitByteFutex - Manages initialization using atomics and the futex syscall
@@ -589,4 +583,10 @@ using SelectedImplementation =
} // end namespace
} // end namespace __cxxabiv1
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#elif defined(__GNUC__)
+# pragma GCC diagnostic pop
+#endif
+
#endif // LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H
lib/libcxxabi/src/fallback_malloc.cpp
@@ -6,9 +6,6 @@
//
//===----------------------------------------------------------------------===//
-// Define _LIBCPP_BUILDING_LIBRARY to ensure _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
-// is only defined when libc aligned allocation is not available.
-#define _LIBCPP_BUILDING_LIBRARY
#include "fallback_malloc.h"
#include <__threading_support>
@@ -20,6 +17,7 @@
#include <stdlib.h> // for malloc, calloc, free
#include <string.h> // for memset
+#include <new> // for std::__libcpp_aligned_{alloc,free}
// A small, simple heap manager based (loosely) on
// the startup heap manager from FreeBSD, optimized for space.
@@ -144,29 +142,26 @@ void fallback_free(void* ptr) {
mutexor mtx(&heap_mutex);
#ifdef DEBUG_FALLBACK_MALLOC
- std::cout << "Freeing item at " << offset_from_node(cp) << " of size "
- << cp->len << std::endl;
+ std::printf("Freeing item at %d of size %d\n", offset_from_node(cp), cp->len);
#endif
for (p = freelist, prev = 0; p && p != list_end;
prev = p, p = node_from_offset(p->next_node)) {
#ifdef DEBUG_FALLBACK_MALLOC
- std::cout << " p, cp, after (p), after(cp) " << offset_from_node(p) << ' '
- << offset_from_node(cp) << ' ' << offset_from_node(after(p))
- << ' ' << offset_from_node(after(cp)) << std::endl;
+ std::printf(" p=%d, cp=%d, after(p)=%d, after(cp)=%d\n",
+ offset_from_node(p), offset_from_node(cp),
+ offset_from_node(after(p)), offset_from_node(after(cp)));
#endif
if (after(p) == cp) {
#ifdef DEBUG_FALLBACK_MALLOC
- std::cout << " Appending onto chunk at " << offset_from_node(p)
- << std::endl;
+ std::printf(" Appending onto chunk at %d\n", offset_from_node(p));
#endif
p->len = static_cast<heap_size>(
p->len + cp->len); // make the free heap_node larger
return;
} else if (after(cp) == p) { // there's a free heap_node right after
#ifdef DEBUG_FALLBACK_MALLOC
- std::cout << " Appending free chunk at " << offset_from_node(p)
- << std::endl;
+ std::printf(" Appending free chunk at %d\n", offset_from_node(p));
#endif
cp->len = static_cast<heap_size>(cp->len + p->len);
if (prev == 0) {
@@ -179,8 +174,7 @@ void fallback_free(void* ptr) {
}
// Nothing to merge with, add it to the start of the free list
#ifdef DEBUG_FALLBACK_MALLOC
- std::cout << " Making new free list entry " << offset_from_node(cp)
- << std::endl;
+ std::printf(" Making new free list entry %d\n", offset_from_node(cp));
#endif
cp->next_node = offset_from_node(freelist);
freelist = cp;
@@ -195,11 +189,11 @@ size_t print_free_list() {
for (p = freelist, prev = 0; p && p != list_end;
prev = p, p = node_from_offset(p->next_node)) {
- std::cout << (prev == 0 ? "" : " ") << "Offset: " << offset_from_node(p)
- << "\tsize: " << p->len << " Next: " << p->next_node << std::endl;
+ std::printf("%sOffset: %d\tsize: %d Next: %d\n",
+ (prev == 0 ? "" : " "), offset_from_node(p), p->len, p->next_node);
total_free += p->len;
}
- std::cout << "Total Free space: " << total_free << std::endl;
+ std::printf("Total Free space: %d\n", total_free);
return total_free;
}
#endif
@@ -211,7 +205,7 @@ struct __attribute__((aligned)) __aligned_type {};
void* __aligned_malloc_with_fallback(size_t size) {
#if defined(_WIN32)
- if (void* dest = _aligned_malloc(size, alignof(__aligned_type)))
+ if (void* dest = std::__libcpp_aligned_alloc(alignof(__aligned_type), size))
return dest;
#elif defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
if (void* dest = ::malloc(size))
@@ -219,8 +213,7 @@ void* __aligned_malloc_with_fallback(size_t size) {
#else
if (size == 0)
size = 1;
- void* dest;
- if (::posix_memalign(&dest, __alignof(__aligned_type), size) == 0)
+ if (void* dest = std::__libcpp_aligned_alloc(__alignof(__aligned_type), size))
return dest;
#endif
return fallback_malloc(size);
@@ -241,10 +234,10 @@ void __aligned_free_with_fallback(void* ptr) {
if (is_fallback_ptr(ptr))
fallback_free(ptr);
else {
-#if defined(_WIN32)
- ::_aligned_free(ptr);
-#else
+#if defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
::free(ptr);
+#else
+ std::__libcpp_aligned_free(ptr);
#endif
}
}
lib/libcxxabi/src/private_typeinfo.cpp
@@ -61,6 +61,16 @@ is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
return x == y || strcmp(x->name(), y->name()) == 0;
}
+static inline ptrdiff_t update_offset_to_base(const char* vtable,
+ ptrdiff_t offset_to_base) {
+#if __has_feature(cxx_abi_relative_vtable)
+ // VTable components are 32 bits in the relative vtables ABI.
+ return *reinterpret_cast<const int32_t*>(vtable + offset_to_base);
+#else
+ return *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
+#endif
+}
+
namespace __cxxabiv1
{
@@ -297,7 +307,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
if (__offset_flags & __virtual_mask)
{
const char* vtable = *static_cast<const char*const*>(adjustedPtr);
- offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
+ offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
}
__base_type->has_unambiguous_public_base(
@@ -615,10 +625,26 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
// Possible future optimization: Take advantage of src2dst_offset
// Get (dynamic_ptr, dynamic_type) from static_ptr
+#if __has_feature(cxx_abi_relative_vtable)
+ // The vtable address will point to the first virtual function, which is 8
+ // bytes after the start of the vtable (4 for the offset from top + 4 for the typeinfo component).
+ const int32_t* vtable =
+ *reinterpret_cast<const int32_t* const*>(static_ptr);
+ int32_t offset_to_derived = vtable[-2];
+ const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
+
+ // The typeinfo component is now a relative offset to a proxy.
+ int32_t offset_to_ti_proxy = vtable[-1];
+ const uint8_t* ptr_to_ti_proxy =
+ reinterpret_cast<const uint8_t*>(vtable) + offset_to_ti_proxy;
+ const __class_type_info* dynamic_type =
+ *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
+#else
void **vtable = *static_cast<void ** const *>(static_ptr);
ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
+#endif
// Initialize answer to nullptr. This will be changed from the search
// results if a non-null answer is found. Regardless, this is what will
@@ -641,6 +667,7 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
{
// We get here only if there is some kind of visibility problem
// in client code.
+ static_assert(std::atomic<size_t>::is_always_lock_free, "");
static std::atomic<size_t> error_count(0);
size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
@@ -667,6 +694,7 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
if (info.path_dst_ptr_to_static_ptr == unknown &&
info.path_dynamic_ptr_to_static_ptr == unknown)
{
+ static_assert(std::atomic<size_t>::is_always_lock_free, "");
static std::atomic<size_t> error_count(0);
size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
@@ -1265,7 +1293,7 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info,
if (__offset_flags & __virtual_mask)
{
const char* vtable = *static_cast<const char*const*>(current_ptr);
- offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
+ offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
__base_type->search_above_dst(info, dst_ptr,
static_cast<const char*>(current_ptr) + offset_to_base,
@@ -1285,7 +1313,7 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info,
if (__offset_flags & __virtual_mask)
{
const char* vtable = *static_cast<const char*const*>(current_ptr);
- offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
+ offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
__base_type->search_below_dst(info,
static_cast<const char*>(current_ptr) + offset_to_base,
lib/libcxxabi/src/stdlib_exception.cpp
@@ -6,7 +6,6 @@
//
//===----------------------------------------------------------------------===//
-#define _LIBCPP_BUILDING_LIBRARY
#include <new>
#include <exception>
lib/libcxxabi/src/stdlib_new_delete.cpp
@@ -8,7 +8,6 @@
// This file implements the new and delete operators.
//===----------------------------------------------------------------------===//
-#define _LIBCPP_BUILDING_LIBRARY
#include "__cxxabi_config.h"
#include <new>
#include <cstdlib>
@@ -28,7 +27,7 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
if (size == 0)
size = 1;
void* p;
- while ((p = ::malloc(size)) == 0)
+ while ((p = ::malloc(size)) == nullptr)
{
// If malloc fails and there is a new_handler,
// call it to try free up memory.
@@ -49,7 +48,7 @@ _LIBCXXABI_WEAK
void*
operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
{
- void* p = 0;
+ void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
@@ -75,7 +74,7 @@ _LIBCXXABI_WEAK
void*
operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
{
- void* p = 0;
+ void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
@@ -143,15 +142,16 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
size = 1;
if (static_cast<size_t>(alignment) < sizeof(void*))
alignment = std::align_val_t(sizeof(void*));
+
+ // Try allocating memory. If allocation fails and there is a new_handler,
+ // call it to try free up memory, and try again until it succeeds, or until
+ // the new_handler decides to terminate.
+ //
+ // If allocation fails and there is no new_handler, we throw bad_alloc
+ // (or return nullptr if exceptions are disabled).
void* p;
-#if defined(_LIBCPP_WIN32API)
- while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr)
-#else
- while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
-#endif
+ while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr)
{
- // If posix_memalign fails and there is a new_handler,
- // call it to try free up memory.
std::new_handler nh = std::get_new_handler();
if (nh)
nh();
@@ -159,7 +159,6 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
#ifndef _LIBCXXABI_NO_EXCEPTIONS
throw std::bad_alloc();
#else
- p = nullptr; // posix_memalign doesn't initialize 'p' on failure
break;
#endif
}
@@ -171,7 +170,7 @@ _LIBCXXABI_WEAK
void*
operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
{
- void* p = 0;
+ void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
@@ -197,7 +196,7 @@ _LIBCXXABI_WEAK
void*
operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
{
- void* p = 0;
+ void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
@@ -216,12 +215,9 @@ _LIBCXXABI_WEAK
void
operator delete(void* ptr, std::align_val_t) _NOEXCEPT
{
- if (ptr)
-#if defined(_LIBCPP_WIN32API)
- ::_aligned_free(ptr);
-#else
- ::free(ptr);
-#endif
+ if (ptr) {
+ std::__libcpp_aligned_free(ptr);
+ }
}
_LIBCXXABI_WEAK
lib/libcxxabi/src/stdlib_stdexcept.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "include/refstring.h"
+#include "../../libcxx/src/include/refstring.h"
#include "stdexcept"
#include "new"
#include <cstdlib>