authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-16 11:55:25+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-16 12:19:09+01:00
log38bf94280bb9735a005673d3eae132f75795b854
tree7b847d81198bb44be21881c201c19e02b53bca60
parentf9a11fbfafa7e056c08350f740af8a96a722a235

Update libcxxabi

llvm commit b2851aea80e5a8f0cfd6c3c5a56a6b00fb28c6b6

11 files changed, 244 insertions(+), 220 deletions(-)

lib/libcxxabi/include/__cxxabi_config.h+15-2
......@@ -18,6 +18,19 @@
1818#define __has_attribute(_attribute_) 0
1919#endif
2020
21#if defined(__clang__)
22# define _LIBCXXABI_COMPILER_CLANG
23# ifndef __apple_build_version__
24# define _LIBCXXABI_CLANG_VER (__clang_major__ * 100 + __clang_minor__)
25# endif
26#elif defined(__GNUC__)
27# define _LIBCXXABI_COMPILER_GCC
28#elif defined(_MSC_VER)
29# define _LIBCXXABI_COMPILER_MSVC
30#elif defined(__IBMCPP__)
31# define _LIBCXXABI_COMPILER_IBM
32#endif
33
2134#if defined(_WIN32)
2235 #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS)
2336 #define _LIBCXXABI_HIDDEN
......@@ -53,7 +66,7 @@
5366 #endif
5467#endif
5568
56#if defined(_WIN32)
69#if defined(_LIBCXXABI_COMPILER_MSVC)
5770#define _LIBCXXABI_WEAK
5871#else
5972#define _LIBCXXABI_WEAK __attribute__((__weak__))
......@@ -72,7 +85,7 @@
7285#endif
7386
7487// wasm32 follows the arm32 ABI convention of using 32-bit guard.
75#if defined(__arm__) || defined(__wasm32__)
88#if defined(__arm__) || defined(__wasm32__) || defined(__ARM64_ARCH_8_32__)
7689# define _LIBCXXABI_GUARD_ABI_ARM
7790#endif
7891
lib/libcxxabi/include/cxxabi.h+10-9
......@@ -21,6 +21,7 @@
2121
2222#define _LIBCPPABI_VERSION 1002
2323#define _LIBCXXABI_NORETURN __attribute__((noreturn))
24#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold))
2425
2526#ifdef __cplusplus
2627
......@@ -78,13 +79,13 @@ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_deleted_virtual(void);
7879
7980// 3.3.2 One-time Construction API
8081#if defined(_LIBCXXABI_GUARD_ABI_ARM)
81extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint32_t *);
82extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint32_t *);
83extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint32_t *);
82extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t *);
83extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t *);
84extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t *);
8485#else
85extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint64_t *);
86extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint64_t *);
87extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint64_t *);
86extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t *);
87extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t *);
88extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t *);
8889#endif
8990
9091// 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,
136137 void (*destructor)(void *));
137138
138139// 3.3.5.3 Runtime API
139extern _LIBCXXABI_FUNC_VIS int __cxa_atexit(void (*f)(void *), void *p,
140 void *d);
141extern _LIBCXXABI_FUNC_VIS int __cxa_finalize(void *);
140// These functions are part of the C++ ABI, but they are not defined in libc++abi:
141// int __cxa_atexit(void (*)(void *), void *, void *);
142// void __cxa_finalize(void *);
142143
143144// 3.4 Demangler API
144145extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name,
lib/libcxxabi/src/cxa_guard_impl.h+24-24
......@@ -54,6 +54,14 @@
5454#endif
5555#endif
5656
57#if defined(__clang__)
58# pragma clang diagnostic push
59# pragma clang diagnostic ignored "-Wtautological-pointer-compare"
60#elif defined(__GNUC__)
61# pragma GCC diagnostic push
62# pragma GCC diagnostic ignored "-Waddress"
63#endif
64
5765// To make testing possible, this header is included from both cxa_guard.cpp
5866// and a number of tests.
5967//
......@@ -112,25 +120,25 @@ class AtomicInt {
112120public:
113121 using MemoryOrder = std::__libcpp_atomic_order;
114122
115 explicit AtomicInt(IntType *b) : b(b) {}
123 explicit AtomicInt(IntType *b) : b_(b) {}
116124 AtomicInt(AtomicInt const&) = delete;
117125 AtomicInt& operator=(AtomicInt const&) = delete;
118126
119127 IntType load(MemoryOrder ord) {
120 return std::__libcpp_atomic_load(b, ord);
128 return std::__libcpp_atomic_load(b_, ord);
121129 }
122130 void store(IntType val, MemoryOrder ord) {
123 std::__libcpp_atomic_store(b, val, ord);
131 std::__libcpp_atomic_store(b_, val, ord);
124132 }
125133 IntType exchange(IntType new_val, MemoryOrder ord) {
126 return std::__libcpp_atomic_exchange(b, new_val, ord);
134 return std::__libcpp_atomic_exchange(b_, new_val, ord);
127135 }
128136 bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
129 return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure);
137 return std::__libcpp_atomic_compare_exchange(b_, expected, desired, ord_success, ord_failure);
130138 }
131139
132140private:
133 IntType *b;
141 IntType *b_;
134142};
135143
136144//===----------------------------------------------------------------------===//
......@@ -154,14 +162,7 @@ constexpr uint32_t (*PlatformThreadID)() = nullptr;
154162
155163
156164constexpr bool PlatformSupportsThreadID() {
157#ifdef __clang__
158#pragma clang diagnostic push
159#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
160#endif
161165 return +PlatformThreadID != nullptr;
162#ifdef __clang__
163#pragma clang diagnostic pop
164#endif
165166}
166167
167168//===----------------------------------------------------------------------===//
......@@ -375,18 +376,18 @@ private:
375376 LockGuard& operator=(LockGuard const&) = delete;
376377
377378 explicit LockGuard(const char* calling_func)
378 : calling_func(calling_func) {
379 : calling_func_(calling_func) {
379380 if (global_mutex.lock())
380 ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func);
381 ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func_);
381382 }
382383
383384 ~LockGuard() {
384385 if (global_mutex.unlock())
385 ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func);
386 ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func_);
386387 }
387388
388389 private:
389 const char* const calling_func;
390 const char* const calling_func_;
390391 };
391392};
392393
......@@ -411,14 +412,7 @@ constexpr void (*PlatformFutexWake)(int*) = nullptr;
411412#endif
412413
413414constexpr bool PlatformSupportsFutex() {
414#ifdef __clang__
415#pragma clang diagnostic push
416#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
417#endif
418415 return +PlatformFutexWait != nullptr;
419#ifdef __clang__
420#pragma clang diagnostic pop
421#endif
422416}
423417
424418/// InitByteFutex - Manages initialization using atomics and the futex syscall
......@@ -589,4 +583,10 @@ using SelectedImplementation =
589583} // end namespace
590584} // end namespace __cxxabiv1
591585
586#if defined(__clang__)
587# pragma clang diagnostic pop
588#elif defined(__GNUC__)
589# pragma GCC diagnostic pop
590#endif
591
592592#endif // LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H
lib/libcxxabi/src/demangle/ItaniumDemangle.h+130-5
......@@ -82,6 +82,7 @@
8282 X(PostfixExpr) \
8383 X(ConditionalExpr) \
8484 X(MemberExpr) \
85 X(SubobjectExpr) \
8586 X(EnclosingExpr) \
8687 X(CastExpr) \
8788 X(SizeofParamPackExpr) \
......@@ -91,6 +92,7 @@
9192 X(PrefixExpr) \
9293 X(FunctionParam) \
9394 X(ConversionExpr) \
95 X(PointerToMemberConversionExpr) \
9496 X(InitListExpr) \
9597 X(FoldExpr) \
9698 X(ThrowExpr) \
......@@ -1656,6 +1658,40 @@ public:
16561658 }
16571659};
16581660
1661class SubobjectExpr : public Node {
1662 const Node *Type;
1663 const Node *SubExpr;
1664 StringView Offset;
1665 NodeArray UnionSelectors;
1666 bool OnePastTheEnd;
1667
1668public:
1669 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1670 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1671 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1672 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1673
1674 template<typename Fn> void match(Fn F) const {
1675 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1676 }
1677
1678 void printLeft(OutputStream &S) const override {
1679 SubExpr->print(S);
1680 S += ".<";
1681 Type->print(S);
1682 S += " at offset ";
1683 if (Offset.empty()) {
1684 S += "0";
1685 } else if (Offset[0] == 'n') {
1686 S += "-";
1687 S += Offset.dropFront();
1688 } else {
1689 S += Offset;
1690 }
1691 S += ">";
1692 }
1693};
1694
16591695class EnclosingExpr : public Node {
16601696 const StringView Prefix;
16611697 const Node *Infix;
......@@ -1843,6 +1879,28 @@ public:
18431879 }
18441880};
18451881
1882class PointerToMemberConversionExpr : public Node {
1883 const Node *Type;
1884 const Node *SubExpr;
1885 StringView Offset;
1886
1887public:
1888 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
1889 StringView Offset_)
1890 : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_),
1891 Offset(Offset_) {}
1892
1893 template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); }
1894
1895 void printLeft(OutputStream &S) const override {
1896 S += "(";
1897 Type->print(S);
1898 S += ")(";
1899 SubExpr->print(S);
1900 S += ")";
1901 }
1902};
1903
18461904class InitListExpr : public Node {
18471905 const Node *Ty;
18481906 NodeArray Inits;
......@@ -2313,9 +2371,9 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
23132371 TemplateParamList Params;
23142372
23152373 public:
2316 ScopedTemplateParamList(AbstractManglingParser *Parser)
2317 : Parser(Parser),
2318 OldNumTemplateParamLists(Parser->TemplateParams.size()) {
2374 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2375 : Parser(TheParser),
2376 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
23192377 Parser->TemplateParams.push_back(&Params);
23202378 }
23212379 ~ScopedTemplateParamList() {
......@@ -2437,6 +2495,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
24372495 Node *parseConversionExpr();
24382496 Node *parseBracedExpr();
24392497 Node *parseFoldExpr();
2498 Node *parsePointerToMemberConversionExpr();
2499 Node *parseSubobjectExpr();
24402500
24412501 /// Parse the <type> production.
24422502 Node *parseType();
......@@ -4404,6 +4464,50 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
44044464 return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);
44054465}
44064466
4467// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4468//
4469// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4470template <typename Derived, typename Alloc>
4471Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr() {
4472 Node *Ty = getDerived().parseType();
4473 if (!Ty)
4474 return nullptr;
4475 Node *Expr = getDerived().parseExpr();
4476 if (!Expr)
4477 return nullptr;
4478 StringView Offset = getDerived().parseNumber(true);
4479 if (!consumeIf('E'))
4480 return nullptr;
4481 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset);
4482}
4483
4484// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4485// <union-selector> ::= _ [<number>]
4486//
4487// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4488template <typename Derived, typename Alloc>
4489Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4490 Node *Ty = getDerived().parseType();
4491 if (!Ty)
4492 return nullptr;
4493 Node *Expr = getDerived().parseExpr();
4494 if (!Expr)
4495 return nullptr;
4496 StringView Offset = getDerived().parseNumber(true);
4497 size_t SelectorsBegin = Names.size();
4498 while (consumeIf('_')) {
4499 Node *Selector = make<NameType>(parseNumber());
4500 if (!Selector)
4501 return nullptr;
4502 Names.push_back(Selector);
4503 }
4504 bool OnePastTheEnd = consumeIf('p');
4505 if (!consumeIf('E'))
4506 return nullptr;
4507 return make<SubobjectExpr>(
4508 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4509}
4510
44074511// <expression> ::= <unary operator-name> <expression>
44084512// ::= <binary operator-name> <expression> <expression>
44094513// ::= <ternary operator-name> <expression> <expression> <expression>
......@@ -4661,6 +4765,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
46614765 return nullptr;
46624766 case 'm':
46634767 switch (First[1]) {
4768 case 'c':
4769 First += 2;
4770 return parsePointerToMemberConversionExpr();
46644771 case 'i':
46654772 First += 2;
46664773 return getDerived().parseBinaryExpr("-");
......@@ -4808,6 +4915,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
48084915 return Ex;
48094916 return make<CastExpr>("static_cast", T, Ex);
48104917 }
4918 case 'o':
4919 First += 2;
4920 return parseSubobjectExpr();
48114921 case 'p': {
48124922 First += 2;
48134923 Node *Child = getDerived().parseExpr();
......@@ -4975,6 +5085,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
49755085 switch (look()) {
49765086 case 'T':
49775087 switch (look(1)) {
5088 // TA <template-arg> # template parameter object
5089 //
5090 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
5091 case 'A': {
5092 First += 2;
5093 Node *Arg = getDerived().parseTemplateArg();
5094 if (Arg == nullptr)
5095 return nullptr;
5096 return make<SpecialName>("template parameter object for ", Arg);
5097 }
49785098 // TV <type> # virtual table
49795099 case 'V': {
49805100 First += 2;
......@@ -5103,7 +5223,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
51035223 decltype(TemplateParams) OldParams;
51045224
51055225 public:
5106 SaveTemplateParams(AbstractManglingParser *Parser) : Parser(Parser) {
5226 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
51075227 OldParams = std::move(Parser->TemplateParams);
51085228 Parser->TemplateParams.clear();
51095229 }
......@@ -5203,7 +5323,12 @@ struct FloatData<long double>
52035323#else
52045324 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
52055325#endif
5206 static const size_t max_demangled_size = 40;
5326 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5327 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5328 // Negatives are one character longer than positives.
5329 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5330 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5331 static const size_t max_demangled_size = 42;
52075332 static constexpr const char *spec = "%LaL";
52085333};
52095334
lib/libcxxabi/src/demangle/Utility.h+1-1
......@@ -52,7 +52,7 @@ class OutputStream {
5252 char *TempPtr = std::end(Temp);
5353
5454 while (N) {
55 *--TempPtr = '0' + char(N % 10);
55 *--TempPtr = char('0' + N % 10);
5656 N /= 10;
5757 }
5858
lib/libcxxabi/src/fallback_malloc.cpp+16-23
......@@ -6,9 +6,6 @@
66//
77//===----------------------------------------------------------------------===//
88
9// Define _LIBCPP_BUILDING_LIBRARY to ensure _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
10// is only defined when libc aligned allocation is not available.
11#define _LIBCPP_BUILDING_LIBRARY
129#include "fallback_malloc.h"
1310
1411#include <__threading_support>
......@@ -20,6 +17,7 @@
2017
2118#include <stdlib.h> // for malloc, calloc, free
2219#include <string.h> // for memset
20#include <new> // for std::__libcpp_aligned_{alloc,free}
2321
2422// A small, simple heap manager based (loosely) on
2523// the startup heap manager from FreeBSD, optimized for space.
......@@ -144,29 +142,26 @@ void fallback_free(void* ptr) {
144142 mutexor mtx(&heap_mutex);
145143
146144#ifdef DEBUG_FALLBACK_MALLOC
147 std::cout << "Freeing item at " << offset_from_node(cp) << " of size "
148 << cp->len << std::endl;
145 std::printf("Freeing item at %d of size %d\n", offset_from_node(cp), cp->len);
149146#endif
150147
151148 for (p = freelist, prev = 0; p && p != list_end;
152149 prev = p, p = node_from_offset(p->next_node)) {
153150#ifdef DEBUG_FALLBACK_MALLOC
154 std::cout << " p, cp, after (p), after(cp) " << offset_from_node(p) << ' '
155 << offset_from_node(cp) << ' ' << offset_from_node(after(p))
156 << ' ' << offset_from_node(after(cp)) << std::endl;
151 std::printf(" p=%d, cp=%d, after(p)=%d, after(cp)=%d\n",
152 offset_from_node(p), offset_from_node(cp),
153 offset_from_node(after(p)), offset_from_node(after(cp)));
157154#endif
158155 if (after(p) == cp) {
159156#ifdef DEBUG_FALLBACK_MALLOC
160 std::cout << " Appending onto chunk at " << offset_from_node(p)
161 << std::endl;
157 std::printf(" Appending onto chunk at %d\n", offset_from_node(p));
162158#endif
163159 p->len = static_cast<heap_size>(
164160 p->len + cp->len); // make the free heap_node larger
165161 return;
166162 } else if (after(cp) == p) { // there's a free heap_node right after
167163#ifdef DEBUG_FALLBACK_MALLOC
168 std::cout << " Appending free chunk at " << offset_from_node(p)
169 << std::endl;
164 std::printf(" Appending free chunk at %d\n", offset_from_node(p));
170165#endif
171166 cp->len = static_cast<heap_size>(cp->len + p->len);
172167 if (prev == 0) {
......@@ -179,8 +174,7 @@ void fallback_free(void* ptr) {
179174 }
180175// Nothing to merge with, add it to the start of the free list
181176#ifdef DEBUG_FALLBACK_MALLOC
182 std::cout << " Making new free list entry " << offset_from_node(cp)
183 << std::endl;
177 std::printf(" Making new free list entry %d\n", offset_from_node(cp));
184178#endif
185179 cp->next_node = offset_from_node(freelist);
186180 freelist = cp;
......@@ -195,11 +189,11 @@ size_t print_free_list() {
195189
196190 for (p = freelist, prev = 0; p && p != list_end;
197191 prev = p, p = node_from_offset(p->next_node)) {
198 std::cout << (prev == 0 ? "" : " ") << "Offset: " << offset_from_node(p)
199 << "\tsize: " << p->len << " Next: " << p->next_node << std::endl;
192 std::printf("%sOffset: %d\tsize: %d Next: %d\n",
193 (prev == 0 ? "" : " "), offset_from_node(p), p->len, p->next_node);
200194 total_free += p->len;
201195 }
202 std::cout << "Total Free space: " << total_free << std::endl;
196 std::printf("Total Free space: %d\n", total_free);
203197 return total_free;
204198}
205199#endif
......@@ -211,7 +205,7 @@ struct __attribute__((aligned)) __aligned_type {};
211205
212206void* __aligned_malloc_with_fallback(size_t size) {
213207#if defined(_WIN32)
214 if (void* dest = _aligned_malloc(size, alignof(__aligned_type)))
208 if (void* dest = std::__libcpp_aligned_alloc(alignof(__aligned_type), size))
215209 return dest;
216210#elif defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
217211 if (void* dest = ::malloc(size))
......@@ -219,8 +213,7 @@ void* __aligned_malloc_with_fallback(size_t size) {
219213#else
220214 if (size == 0)
221215 size = 1;
222 void* dest;
223 if (::posix_memalign(&dest, __alignof(__aligned_type), size) == 0)
216 if (void* dest = std::__libcpp_aligned_alloc(__alignof(__aligned_type), size))
224217 return dest;
225218#endif
226219 return fallback_malloc(size);
......@@ -241,10 +234,10 @@ void __aligned_free_with_fallback(void* ptr) {
241234 if (is_fallback_ptr(ptr))
242235 fallback_free(ptr);
243236 else {
244#if defined(_WIN32)
245 ::_aligned_free(ptr);
246#else
237#if defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
247238 ::free(ptr);
239#else
240 std::__libcpp_aligned_free(ptr);
248241#endif
249242 }
250243}
lib/libcxxabi/src/include/refstring.h deleted-131
......@@ -1,131 +0,0 @@
1//===------------------------ __refstring ---------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// FIXME: This file is copied from libcxx/src/include/refstring.h. Instead of
10// duplicating the file in libc++abi we should require that the libc++ sources
11// are available when building libc++abi.
12
13#ifndef _LIBCPPABI_REFSTRING_H
14#define _LIBCPPABI_REFSTRING_H
15
16#include <__config>
17#include <stdexcept>
18#include <cstddef>
19#include <cstring>
20#ifdef __APPLE__
21#include <dlfcn.h>
22#include <mach-o/dyld.h>
23#endif
24#include "atomic_support.h"
25
26_LIBCPP_BEGIN_NAMESPACE_STD
27
28namespace __refstring_imp { namespace {
29typedef int count_t;
30
31struct _Rep_base {
32 std::size_t len;
33 std::size_t cap;
34 count_t count;
35};
36
37inline _Rep_base* rep_from_data(const char *data_) noexcept {
38 char *data = const_cast<char *>(data_);
39 return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base));
40}
41
42inline char * data_from_rep(_Rep_base *rep) noexcept {
43 char *data = reinterpret_cast<char *>(rep);
44 return data + sizeof(*rep);
45}
46
47#if defined(__APPLE__)
48inline
49const char* compute_gcc_empty_string_storage() _NOEXCEPT
50{
51 void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD);
52 if (handle == nullptr)
53 return nullptr;
54 void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE");
55 if (sym == nullptr)
56 return nullptr;
57 return data_from_rep(reinterpret_cast<_Rep_base *>(sym));
58}
59
60inline
61const char*
62get_gcc_empty_string_storage() _NOEXCEPT
63{
64 static const char* p = compute_gcc_empty_string_storage();
65 return p;
66}
67#endif
68
69}} // namespace __refstring_imp
70
71using namespace __refstring_imp;
72
73inline
74__libcpp_refstring::__libcpp_refstring(const char* msg) {
75 std::size_t len = strlen(msg);
76 _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1));
77 rep->len = len;
78 rep->cap = len;
79 rep->count = 0;
80 char *data = data_from_rep(rep);
81 std::memcpy(data, msg, len + 1);
82 __imp_ = data;
83}
84
85inline
86__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT
87 : __imp_(s.__imp_)
88{
89 if (__uses_refcount())
90 __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1);
91}
92
93inline
94__libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT {
95 bool adjust_old_count = __uses_refcount();
96 struct _Rep_base *old_rep = rep_from_data(__imp_);
97 __imp_ = s.__imp_;
98 if (__uses_refcount())
99 __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1);
100 if (adjust_old_count)
101 {
102 if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0)
103 {
104 ::operator delete(old_rep);
105 }
106 }
107 return *this;
108}
109
110inline
111__libcpp_refstring::~__libcpp_refstring() {
112 if (__uses_refcount()) {
113 _Rep_base* rep = rep_from_data(__imp_);
114 if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) {
115 ::operator delete(rep);
116 }
117 }
118}
119
120inline
121bool __libcpp_refstring::__uses_refcount() const {
122#ifdef __APPLE__
123 return __imp_ != get_gcc_empty_string_storage();
124#else
125 return true;
126#endif
127}
128
129_LIBCPP_END_NAMESPACE_STD
130
131#endif //_LIBCPPABI_REFSTRING_H
lib/libcxxabi/src/private_typeinfo.cpp+31-3
......@@ -61,6 +61,16 @@ is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
6161 return x == y || strcmp(x->name(), y->name()) == 0;
6262}
6363
64static inline ptrdiff_t update_offset_to_base(const char* vtable,
65 ptrdiff_t offset_to_base) {
66#if __has_feature(cxx_abi_relative_vtable)
67 // VTable components are 32 bits in the relative vtables ABI.
68 return *reinterpret_cast<const int32_t*>(vtable + offset_to_base);
69#else
70 return *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
71#endif
72}
73
6474namespace __cxxabiv1
6575{
6676
......@@ -297,7 +307,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
297307 if (__offset_flags & __virtual_mask)
298308 {
299309 const char* vtable = *static_cast<const char*const*>(adjustedPtr);
300 offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
310 offset_to_base = update_offset_to_base(vtable, offset_to_base);
301311 }
302312 }
303313 __base_type->has_unambiguous_public_base(
......@@ -615,10 +625,26 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
615625 // Possible future optimization: Take advantage of src2dst_offset
616626
617627 // Get (dynamic_ptr, dynamic_type) from static_ptr
628#if __has_feature(cxx_abi_relative_vtable)
629 // The vtable address will point to the first virtual function, which is 8
630 // bytes after the start of the vtable (4 for the offset from top + 4 for the typeinfo component).
631 const int32_t* vtable =
632 *reinterpret_cast<const int32_t* const*>(static_ptr);
633 int32_t offset_to_derived = vtable[-2];
634 const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
635
636 // The typeinfo component is now a relative offset to a proxy.
637 int32_t offset_to_ti_proxy = vtable[-1];
638 const uint8_t* ptr_to_ti_proxy =
639 reinterpret_cast<const uint8_t*>(vtable) + offset_to_ti_proxy;
640 const __class_type_info* dynamic_type =
641 *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
642#else
618643 void **vtable = *static_cast<void ** const *>(static_ptr);
619644 ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
620645 const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
621646 const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
647#endif
622648
623649 // Initialize answer to nullptr. This will be changed from the search
624650 // 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,
641667 {
642668 // We get here only if there is some kind of visibility problem
643669 // in client code.
670 static_assert(std::atomic<size_t>::is_always_lock_free, "");
644671 static std::atomic<size_t> error_count(0);
645672 size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
646673 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,
667694 if (info.path_dst_ptr_to_static_ptr == unknown &&
668695 info.path_dynamic_ptr_to_static_ptr == unknown)
669696 {
697 static_assert(std::atomic<size_t>::is_always_lock_free, "");
670698 static std::atomic<size_t> error_count(0);
671699 size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
672700 if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
......@@ -1265,7 +1293,7 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info,
12651293 if (__offset_flags & __virtual_mask)
12661294 {
12671295 const char* vtable = *static_cast<const char*const*>(current_ptr);
1268 offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
1296 offset_to_base = update_offset_to_base(vtable, offset_to_base);
12691297 }
12701298 __base_type->search_above_dst(info, dst_ptr,
12711299 static_cast<const char*>(current_ptr) + offset_to_base,
......@@ -1285,7 +1313,7 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info,
12851313 if (__offset_flags & __virtual_mask)
12861314 {
12871315 const char* vtable = *static_cast<const char*const*>(current_ptr);
1288 offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
1316 offset_to_base = update_offset_to_base(vtable, offset_to_base);
12891317 }
12901318 __base_type->search_below_dst(info,
12911319 static_cast<const char*>(current_ptr) + offset_to_base,
lib/libcxxabi/src/stdlib_exception.cpp-1
......@@ -6,7 +6,6 @@
66//
77//===----------------------------------------------------------------------===//
88
9#define _LIBCPP_BUILDING_LIBRARY
109#include <new>
1110#include <exception>
1211
lib/libcxxabi/src/stdlib_new_delete.cpp+16-20
......@@ -8,7 +8,6 @@
88// This file implements the new and delete operators.
99//===----------------------------------------------------------------------===//
1010
11#define _LIBCPP_BUILDING_LIBRARY
1211#include "__cxxabi_config.h"
1312#include <new>
1413#include <cstdlib>
......@@ -28,7 +27,7 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
2827 if (size == 0)
2928 size = 1;
3029 void* p;
31 while ((p = ::malloc(size)) == 0)
30 while ((p = ::malloc(size)) == nullptr)
3231 {
3332 // If malloc fails and there is a new_handler,
3433 // call it to try free up memory.
......@@ -49,7 +48,7 @@ _LIBCXXABI_WEAK
4948void*
5049operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
5150{
52 void* p = 0;
51 void* p = nullptr;
5352#ifndef _LIBCXXABI_NO_EXCEPTIONS
5453 try
5554 {
......@@ -75,7 +74,7 @@ _LIBCXXABI_WEAK
7574void*
7675operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
7776{
78 void* p = 0;
77 void* p = nullptr;
7978#ifndef _LIBCXXABI_NO_EXCEPTIONS
8079 try
8180 {
......@@ -143,15 +142,16 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
143142 size = 1;
144143 if (static_cast<size_t>(alignment) < sizeof(void*))
145144 alignment = std::align_val_t(sizeof(void*));
145
146 // Try allocating memory. If allocation fails and there is a new_handler,
147 // call it to try free up memory, and try again until it succeeds, or until
148 // the new_handler decides to terminate.
149 //
150 // If allocation fails and there is no new_handler, we throw bad_alloc
151 // (or return nullptr if exceptions are disabled).
146152 void* p;
147#if defined(_LIBCPP_WIN32API)
148 while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr)
149#else
150 while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
151#endif
153 while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr)
152154 {
153 // If posix_memalign fails and there is a new_handler,
154 // call it to try free up memory.
155155 std::new_handler nh = std::get_new_handler();
156156 if (nh)
157157 nh();
......@@ -159,7 +159,6 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
159159#ifndef _LIBCXXABI_NO_EXCEPTIONS
160160 throw std::bad_alloc();
161161#else
162 p = nullptr; // posix_memalign doesn't initialize 'p' on failure
163162 break;
164163#endif
165164 }
......@@ -171,7 +170,7 @@ _LIBCXXABI_WEAK
171170void*
172171operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
173172{
174 void* p = 0;
173 void* p = nullptr;
175174#ifndef _LIBCXXABI_NO_EXCEPTIONS
176175 try
177176 {
......@@ -197,7 +196,7 @@ _LIBCXXABI_WEAK
197196void*
198197operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
199198{
200 void* p = 0;
199 void* p = nullptr;
201200#ifndef _LIBCXXABI_NO_EXCEPTIONS
202201 try
203202 {
......@@ -216,12 +215,9 @@ _LIBCXXABI_WEAK
216215void
217216operator delete(void* ptr, std::align_val_t) _NOEXCEPT
218217{
219 if (ptr)
220#if defined(_LIBCPP_WIN32API)
221 ::_aligned_free(ptr);
222#else
223 ::free(ptr);
224#endif
218 if (ptr) {
219 std::__libcpp_aligned_free(ptr);
220 }
225221}
226222
227223_LIBCXXABI_WEAK
lib/libcxxabi/src/stdlib_stdexcept.cpp+1-1
......@@ -6,7 +6,7 @@
66//
77//===----------------------------------------------------------------------===//
88
9#include "include/refstring.h"
9#include "../../libcxx/src/include/refstring.h"
1010#include "stdexcept"
1111#include "new"
1212#include <cstdlib>