mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
Update libcxxabi
llvm commit b2851aea80e5a8f0cfd6c3c5a56a6b00fb28c6b6
This commit is contained in:
parent
f9a11fbfaf
commit
38bf94280b
@ -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
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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";
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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,
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define _LIBCPP_BUILDING_LIBRARY
|
||||
#include <new>
|
||||
#include <exception>
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "include/refstring.h"
|
||||
#include "../../libcxx/src/include/refstring.h"
|
||||
#include "stdexcept"
|
||||
#include "new"
|
||||
#include <cstdlib>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user