authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-26 13:23:18-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-26 16:36:13-07:00
loge41b58ddc3e20144d30bba8c1387df5aa5fd6c5e
tree2aee9d8b7085704906f67e4e403bfaad29c06cf4
parent1eaf180dd04efcf65ef981b1e1064658b5ec09c3

update libcxxabi to llvm 16


6 files changed, 138 insertions(+), 50 deletions(-)

lib/libcxxabi/src/aix_state_tab_eh.inc+42-8
...@@ -14,6 +14,10 @@...@@ -14,6 +14,10 @@
14#include <stdio.h>14#include <stdio.h>
15#include <sys/debug.h>15#include <sys/debug.h>
1616
17#if !__has_cpp_attribute(clang::optnone)
18#error This file requires clang::optnone attribute support
19#endif
20
17/*21/*
18 The legacy IBM xlC and xlclang++ compilers use the state table for EH22 The legacy IBM xlC and xlclang++ compilers use the state table for EH
19 instead of the range table. Destructors, or addresses of the possible catch23 instead of the range table. Destructors, or addresses of the possible catch
...@@ -183,10 +187,6 @@ enum FSMMagic : uint32_t {...@@ -183,10 +187,6 @@ enum FSMMagic : uint32_t {
183 number3 = 0x1cedbeef // State table generated by xlclang++ compiler.187 number3 = 0x1cedbeef // State table generated by xlclang++ compiler.
184};188};
185189
186constexpr uint32_t REG_EXCP_OBJ = 14; // Register to pass the address of the exception
187 // object from the personality to xlclang++
188 // compiled code.
189
190constexpr size_t dtorArgument = 0x02; // Flag to destructor indicating to free190constexpr size_t dtorArgument = 0x02; // Flag to destructor indicating to free
191 // virtual bases, don't delete object.191 // virtual bases, don't delete object.
192192
...@@ -555,8 +555,16 @@ __xlcxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionCl...@@ -555,8 +555,16 @@ __xlcxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionCl
555 if (actions & _UA_CLEANUP_PHASE) {555 if (actions & _UA_CLEANUP_PHASE) {
556 // Phase 2 cleanup:556 // Phase 2 cleanup:
557 if (results.reason == _URC_HANDLER_FOUND) {557 if (results.reason == _URC_HANDLER_FOUND) {
558 // Store the address of unwind_exception in the stack field
559 // reserved for compilers (SP + 3 * sizeof(uintptr_t)) in the stack of
560 // the caller of the function containing the landing pad (within the link
561 // area for the call to the latter) for __xlc_exception_handle()
562 // to retrieve when it is called by the landing pad.
563 uintptr_t *currentSP = reinterpret_cast<uintptr_t*>(_Unwind_GetGR(context, 1));
564 uintptr_t *callersSP = reinterpret_cast<uintptr_t*>(currentSP[0]);
565 callersSP[3] = reinterpret_cast<uintptr_t>(unwind_exception);
566 _LIBCXXABI_TRACE_STATETAB("Handshake: set unwind_exception=%p in stack=%p\n", reinterpret_cast<void*>(unwind_exception), reinterpret_cast<void*>(callersSP));
558 // Jump to the handler.567 // Jump to the handler.
559 _Unwind_SetGR(context, REG_EXCP_OBJ, reinterpret_cast<uintptr_t>(unwind_exception));
560 _Unwind_SetIP(context, results.landingPad);568 _Unwind_SetIP(context, results.landingPad);
561 return _URC_INSTALL_CONTEXT;569 return _URC_INSTALL_CONTEXT;
562 }570 }
...@@ -633,12 +641,38 @@ _LIBCXXABI_FUNC_VIS void __xlc_throw_badexception() {...@@ -633,12 +641,38 @@ _LIBCXXABI_FUNC_VIS void __xlc_throw_badexception() {
633 __cxa_throw(newexception, const_cast<std::type_info*>(&typeid(std::bad_exception)), 0);641 __cxa_throw(newexception, const_cast<std::type_info*>(&typeid(std::bad_exception)), 0);
634}642}
635643
644// force_a_stackframe
645// This function is called by __xlc_exception_handle() to ensure a stack frame
646// is created for __xlc_exception_handle().
647__attribute__((noinline, optnone))
648static void force_a_stackframe() {}
649
636// __xlc_exception_handle650// __xlc_exception_handle
637// This function is for xlclang++. It returns the address of the exception651// This function is for xlclang++. It returns the address of the exception
638// object set in gpr14 by the personality routine for xlclang++ compiled code.652// object stored in the reserved field in the stack of the caller of the
653// function that calls __xlc_exception_handle() (within the link area for the
654// call to the latter). The address is stored by the personality routine for
655// xlclang++ compiled code. The implementation of __xlc_exception_handle()
656// assumes a stack frame is created for it. The following ensures this
657// assumption holds true: 1) a call to force_a_stackframe() is made inside
658// __xlc_exception_handle() to make it non-leaf; and 2) optimizations are
659// disabled for this function with attribute 'optnone'. Note: this function
660// may not work as expected if these are changed.
661__attribute__((optnone))
639_LIBCXXABI_FUNC_VIS uintptr_t __xlc_exception_handle() {662_LIBCXXABI_FUNC_VIS uintptr_t __xlc_exception_handle() {
640 uintptr_t exceptionObject;663 // Make a call to force_a_stackframe() so that the compiler creates a stack
641 asm("mr %0, 14" : "=r"(exceptionObject));664 // frame for this function.
665 force_a_stackframe();
666
667 // Get the SP of this function, i.e., __xlc_exception_handle().
668 uintptr_t *lastStack;
669 asm("mr %0, 1" : "=r"(lastStack));
670 // Get the SP of the caller of __xlc_exception_handle().
671 uintptr_t *callerStack = reinterpret_cast<uintptr_t*>(lastStack[0]);
672 // Get the SP of the caller of the caller.
673 uintptr_t *callerStack2 = reinterpret_cast<uintptr_t*>(callerStack[0]);
674 uintptr_t exceptionObject = callerStack2[3];
675 _LIBCXXABI_TRACE_STATETAB("Handshake: exceptionObject=%p from stack=%p\n", reinterpret_cast<void*>(exceptionObject), reinterpret_cast<void*>(callerStack2));
642 return exceptionObject;676 return exceptionObject;
643}677}
644678
lib/libcxxabi/src/cxa_demangle.cpp+1-4
...@@ -386,15 +386,12 @@ __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {...@@ -386,15 +386,12 @@ __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {
386386
387 int InternalStatus = demangle_success;387 int InternalStatus = demangle_success;
388 Demangler Parser(MangledName, MangledName + std::strlen(MangledName));388 Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
389 OutputBuffer O;
390
391 Node *AST = Parser.parse();389 Node *AST = Parser.parse();
392390
393 if (AST == nullptr)391 if (AST == nullptr)
394 InternalStatus = demangle_invalid_mangled_name;392 InternalStatus = demangle_invalid_mangled_name;
395 else if (!initializeOutputBuffer(Buf, N, O, 1024))
396 InternalStatus = demangle_memory_alloc_failure;
397 else {393 else {
394 OutputBuffer O(Buf, N);
398 assert(Parser.ForwardTemplateRefs.empty());395 assert(Parser.ForwardTemplateRefs.empty());
399 AST->print(O);396 AST->print(O);
400 O += '\0';397 O += '\0';
lib/libcxxabi/src/cxa_guard_impl.h+5-1
...@@ -5,6 +5,7 @@...@@ -5,6 +5,7 @@
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//6//
7//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
8
8#ifndef LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H9#ifndef LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H
9#define LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H10#define LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H
1011
...@@ -54,9 +55,12 @@...@@ -54,9 +55,12 @@
54# endif55# endif
55#endif56#endif
5657
58#include <__threading_support>
59#include <cstdint>
60#include <cstring>
57#include <limits.h>61#include <limits.h>
58#include <stdlib.h>62#include <stdlib.h>
59#include <__threading_support>63
60#ifndef _LIBCXXABI_HAS_NO_THREADS64#ifndef _LIBCXXABI_HAS_NO_THREADS
61# if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)65# if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
62# pragma comment(lib, "pthread")66# pragma comment(lib, "pthread")
lib/libcxxabi/src/demangle/ItaniumDemangle.h+26-6
...@@ -26,6 +26,7 @@...@@ -26,6 +26,7 @@
26#include <cstdlib>26#include <cstdlib>
27#include <cstring>27#include <cstring>
28#include <limits>28#include <limits>
29#include <new>
29#include <utility>30#include <utility>
3031
31DEMANGLE_NAMESPACE_BEGIN32DEMANGLE_NAMESPACE_BEGIN
...@@ -369,6 +370,10 @@ public:...@@ -369,6 +370,10 @@ public:
369 VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_)370 VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_)
370 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}371 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
371372
373 const Node *getTy() const { return Ty; }
374 StringView getExt() const { return Ext; }
375 const Node *getTA() const { return TA; }
376
372 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }377 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
373378
374 void printLeft(OutputBuffer &OB) const override {379 void printLeft(OutputBuffer &OB) const override {
...@@ -417,6 +422,9 @@ public:...@@ -417,6 +422,9 @@ public:
417 Child_->ArrayCache, Child_->FunctionCache),422 Child_->ArrayCache, Child_->FunctionCache),
418 Quals(Quals_), Child(Child_) {}423 Quals(Quals_), Child(Child_) {}
419424
425 Qualifiers getQuals() const { return Quals; }
426 const Node *getChild() const { return Child; }
427
420 template<typename Fn> void match(Fn F) const { F(Child, Quals); }428 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
421429
422 bool hasRHSComponentSlow(OutputBuffer &OB) const override {430 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
...@@ -585,6 +593,8 @@ public:...@@ -585,6 +593,8 @@ public:
585 : Node(KPointerType, Pointee_->RHSComponentCache),593 : Node(KPointerType, Pointee_->RHSComponentCache),
586 Pointee(Pointee_) {}594 Pointee(Pointee_) {}
587595
596 const Node *getPointee() const { return Pointee; }
597
588 template<typename Fn> void match(Fn F) const { F(Pointee); }598 template<typename Fn> void match(Fn F) const { F(Pointee); }
589599
590 bool hasRHSComponentSlow(OutputBuffer &OB) const override {600 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
...@@ -1070,6 +1080,9 @@ public:...@@ -1070,6 +1080,9 @@ public:
1070 VectorType(const Node *BaseType_, const Node *Dimension_)1080 VectorType(const Node *BaseType_, const Node *Dimension_)
1071 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}1081 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}
10721082
1083 const Node *getBaseType() const { return BaseType; }
1084 const Node *getDimension() const { return Dimension; }
1085
1073 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }1086 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
10741087
1075 void printLeft(OutputBuffer &OB) const override {1088 void printLeft(OutputBuffer &OB) const override {
...@@ -3019,14 +3032,21 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {...@@ -3019,14 +3032,21 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
3019 if (numLeft() < 2)3032 if (numLeft() < 2)
3020 return nullptr;3033 return nullptr;
30213034
3022 auto Op = std::lower_bound(3035 // We can't use lower_bound as that can link to symbols in the C++ library,
3023 &Ops[0], &Ops[NumOps], First,3036 // and this must remain independant of that.
3024 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });3037 size_t lower = 0u, upper = NumOps - 1; // Inclusive bounds.
3025 if (Op == &Ops[NumOps] || *Op != First)3038 while (upper != lower) {
3039 size_t middle = (upper + lower) / 2;
3040 if (Ops[middle] < First)
3041 lower = middle + 1;
3042 else
3043 upper = middle;
3044 }
3045 if (Ops[lower] != First)
3026 return nullptr;3046 return nullptr;
30273047
3028 First += 2;3048 First += 2;
3029 return Op;3049 return &Ops[lower];
3030}3050}
30313051
3032// <operator-name> ::= See parseOperatorEncoding()3052// <operator-name> ::= See parseOperatorEncoding()
...@@ -5099,7 +5119,7 @@ template <>...@@ -5099,7 +5119,7 @@ template <>
5099struct FloatData<long double>5119struct FloatData<long double>
5100{5120{
5101#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \5121#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5102 defined(__wasm__) || defined(__riscv)5122 defined(__wasm__) || defined(__riscv) || defined(__loongarch__)
5103 static const size_t mangled_size = 32;5123 static const size_t mangled_size = 32;
5104#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)5124#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5105 static const size_t mangled_size = 16;5125 static const size_t mangled_size = 16;
lib/libcxxabi/src/demangle/Utility.h+3-22
...@@ -69,7 +69,9 @@ class OutputBuffer {...@@ -69,7 +69,9 @@ class OutputBuffer {
6969
70public:70public:
71 OutputBuffer(char *StartBuf, size_t Size)71 OutputBuffer(char *StartBuf, size_t Size)
72 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}72 : Buffer(StartBuf), BufferCapacity(Size) {}
73 OutputBuffer(char *StartBuf, size_t *SizePtr)
74 : OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}
73 OutputBuffer() = default;75 OutputBuffer() = default;
74 // Non-copyable76 // Non-copyable
75 OutputBuffer(const OutputBuffer &) = delete;77 OutputBuffer(const OutputBuffer &) = delete;
...@@ -77,12 +79,6 @@ public:...@@ -77,12 +79,6 @@ public:
7779
78 operator StringView() const { return StringView(Buffer, CurrentPosition); }80 operator StringView() const { return StringView(Buffer, CurrentPosition); }
7981
80 void reset(char *Buffer_, size_t BufferCapacity_) {
81 CurrentPosition = 0;
82 Buffer = Buffer_;
83 BufferCapacity = BufferCapacity_;
84 }
85
86 /// If a ParameterPackExpansion (or similar type) is encountered, the offset82 /// If a ParameterPackExpansion (or similar type) is encountered, the offset
87 /// into the pack that we're currently printing.83 /// into the pack that we're currently printing.
88 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();84 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
...@@ -198,21 +194,6 @@ public:...@@ -198,21 +194,6 @@ public:
198 ScopedOverride &operator=(const ScopedOverride &) = delete;194 ScopedOverride &operator=(const ScopedOverride &) = delete;
199};195};
200196
201inline bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB,
202 size_t InitSize) {
203 size_t BufferSize;
204 if (Buf == nullptr) {
205 Buf = static_cast<char *>(std::malloc(InitSize));
206 if (Buf == nullptr)
207 return false;
208 BufferSize = InitSize;
209 } else
210 BufferSize = *N;
211
212 OB.reset(Buf, BufferSize);
213 return true;
214}
215
216DEMANGLE_NAMESPACE_END197DEMANGLE_NAMESPACE_END
217198
218#endif199#endif
lib/libcxxabi/src/fallback_malloc.cpp+61-9
...@@ -15,6 +15,7 @@...@@ -15,6 +15,7 @@
15#endif15#endif
16#endif16#endif
1717
18#include <assert.h>
18#include <stdlib.h> // for malloc, calloc, free19#include <stdlib.h> // for malloc, calloc, free
19#include <string.h> // for memset20#include <string.h> // for memset
20#include <new> // for std::__libcpp_aligned_{alloc,free}21#include <new> // for std::__libcpp_aligned_{alloc,free}
...@@ -63,11 +64,28 @@ char heap[HEAP_SIZE] __attribute__((aligned));...@@ -63,11 +64,28 @@ char heap[HEAP_SIZE] __attribute__((aligned));
63typedef unsigned short heap_offset;64typedef unsigned short heap_offset;
64typedef unsigned short heap_size;65typedef unsigned short heap_size;
6566
67// On both 64 and 32 bit targets heap_node should have the following properties
68// Size: 4
69// Alignment: 2
66struct heap_node {70struct heap_node {
67 heap_offset next_node; // offset into heap71 heap_offset next_node; // offset into heap
68 heap_size len; // size in units of "sizeof(heap_node)"72 heap_size len; // size in units of "sizeof(heap_node)"
69};73};
7074
75// All pointers returned by fallback_malloc must be at least aligned
76// as RequiredAligned. Note that RequiredAlignment can be greater than
77// alignof(std::max_align_t) on 64 bit systems compiling 32 bit code.
78struct FallbackMaxAlignType {
79} __attribute__((aligned));
80const size_t RequiredAlignment = alignof(FallbackMaxAlignType);
81
82static_assert(alignof(FallbackMaxAlignType) % sizeof(heap_node) == 0,
83 "The required alignment must be evenly divisible by the sizeof(heap_node)");
84
85// The number of heap_node's that can fit in a chunk of memory with the size
86// of the RequiredAlignment. On 64 bit targets NodesPerAlignment should be 4.
87const size_t NodesPerAlignment = alignof(FallbackMaxAlignType) / sizeof(heap_node);
88
71static const heap_node* list_end =89static const heap_node* list_end =
72 (heap_node*)(&heap[HEAP_SIZE]); // one past the end of the heap90 (heap_node*)(&heap[HEAP_SIZE]); // one past the end of the heap
73static heap_node* freelist = NULL;91static heap_node* freelist = NULL;
...@@ -82,10 +100,23 @@ heap_offset offset_from_node(const heap_node* ptr) {...@@ -82,10 +100,23 @@ heap_offset offset_from_node(const heap_node* ptr) {
82 sizeof(heap_node));100 sizeof(heap_node));
83}101}
84102
103// Return a pointer to the first address, 'A', in `heap` that can actually be
104// used to represent a heap_node. 'A' must be aligned so that
105// '(A + sizeof(heap_node)) % RequiredAlignment == 0'. On 64 bit systems this
106// address should be 12 bytes after the first 16 byte boundary.
107heap_node* getFirstAlignedNodeInHeap() {
108 heap_node* node = (heap_node*)heap;
109 const size_t alignNBytesAfterBoundary = RequiredAlignment - sizeof(heap_node);
110 size_t boundaryOffset = reinterpret_cast<size_t>(node) % RequiredAlignment;
111 size_t requiredOffset = alignNBytesAfterBoundary - boundaryOffset;
112 size_t NElemOffset = requiredOffset / sizeof(heap_node);
113 return node + NElemOffset;
114}
115
85void init_heap() {116void init_heap() {
86 freelist = (heap_node*)heap;117 freelist = getFirstAlignedNodeInHeap();
87 freelist->next_node = offset_from_node(list_end);118 freelist->next_node = offset_from_node(list_end);
88 freelist->len = HEAP_SIZE / sizeof(heap_node);119 freelist->len = static_cast<heap_size>(list_end - freelist);
89}120}
90121
91// How big a chunk we allocate122// How big a chunk we allocate
...@@ -109,23 +140,44 @@ void* fallback_malloc(size_t len) {...@@ -109,23 +140,44 @@ void* fallback_malloc(size_t len) {
109 for (p = freelist, prev = 0; p && p != list_end;140 for (p = freelist, prev = 0; p && p != list_end;
110 prev = p, p = node_from_offset(p->next_node)) {141 prev = p, p = node_from_offset(p->next_node)) {
111142
112 if (p->len > nelems) { // chunk is larger, shorten, and return the tail143 // Check the invariant that all heap_nodes pointers 'p' are aligned
113 heap_node* q;144 // so that 'p + 1' has an alignment of at least RequiredAlignment
145 assert(reinterpret_cast<size_t>(p + 1) % RequiredAlignment == 0);
146
147 // Calculate the number of extra padding elements needed in order
148 // to split 'p' and create a properly aligned heap_node from the tail
149 // of 'p'. We calculate aligned_nelems such that 'p->len - aligned_nelems'
150 // will be a multiple of NodesPerAlignment.
151 size_t aligned_nelems = nelems;
152 if (p->len > nelems) {
153 heap_size remaining_len = static_cast<heap_size>(p->len - nelems);
154 aligned_nelems += remaining_len % NodesPerAlignment;
155 }
114156
115 p->len = static_cast<heap_size>(p->len - nelems);157 // chunk is larger and we can create a properly aligned heap_node
158 // from the tail. In this case we shorten 'p' and return the tail.
159 if (p->len > aligned_nelems) {
160 heap_node* q;
161 p->len = static_cast<heap_size>(p->len - aligned_nelems);
116 q = p + p->len;162 q = p + p->len;
117 q->next_node = 0;163 q->next_node = 0;
118 q->len = static_cast<heap_size>(nelems);164 q->len = static_cast<heap_size>(aligned_nelems);
119 return (void*)(q + 1);165 void* ptr = q + 1;
166 assert(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0);
167 return ptr;
120 }168 }
121169
122 if (p->len == nelems) { // exact size match170 // The chunk is the exact size or the chunk is larger but not large
171 // enough to split due to alignment constraints.
172 if (p->len >= nelems) {
123 if (prev == 0)173 if (prev == 0)
124 freelist = node_from_offset(p->next_node);174 freelist = node_from_offset(p->next_node);
125 else175 else
126 prev->next_node = p->next_node;176 prev->next_node = p->next_node;
127 p->next_node = 0;177 p->next_node = 0;
128 return (void*)(p + 1);178 void* ptr = p + 1;
179 assert(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0);
180 return ptr;
129 }181 }
130 }182 }
131 return NULL; // couldn't find a spot big enough183 return NULL; // couldn't find a spot big enough