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 @@
1414#include <stdio.h>
1515#include <sys/debug.h>
1616
17#if !__has_cpp_attribute(clang::optnone)
18#error This file requires clang::optnone attribute support
19#endif
20
1721/*
1822 The legacy IBM xlC and xlclang++ compilers use the state table for EH
1923 instead of the range table. Destructors, or addresses of the possible catch
......@@ -183,10 +187,6 @@ enum FSMMagic : uint32_t {
183187 number3 = 0x1cedbeef // State table generated by xlclang++ compiler.
184188};
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
190190constexpr size_t dtorArgument = 0x02; // Flag to destructor indicating to free
191191 // virtual bases, don't delete object.
192192
......@@ -555,8 +555,16 @@ __xlcxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionCl
555555 if (actions & _UA_CLEANUP_PHASE) {
556556 // Phase 2 cleanup:
557557 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));
558567 // Jump to the handler.
559 _Unwind_SetGR(context, REG_EXCP_OBJ, reinterpret_cast<uintptr_t>(unwind_exception));
560568 _Unwind_SetIP(context, results.landingPad);
561569 return _URC_INSTALL_CONTEXT;
562570 }
......@@ -633,12 +641,38 @@ _LIBCXXABI_FUNC_VIS void __xlc_throw_badexception() {
633641 __cxa_throw(newexception, const_cast<std::type_info*>(&typeid(std::bad_exception)), 0);
634642}
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
636650// __xlc_exception_handle
637651// 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))
639662_LIBCXXABI_FUNC_VIS uintptr_t __xlc_exception_handle() {
640 uintptr_t exceptionObject;
641 asm("mr %0, 14" : "=r"(exceptionObject));
663 // Make a call to force_a_stackframe() so that the compiler creates a stack
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));
642676 return exceptionObject;
643677}
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) {
386386
387387 int InternalStatus = demangle_success;
388388 Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
389 OutputBuffer O;
390
391389 Node *AST = Parser.parse();
392390
393391 if (AST == nullptr)
394392 InternalStatus = demangle_invalid_mangled_name;
395 else if (!initializeOutputBuffer(Buf, N, O, 1024))
396 InternalStatus = demangle_memory_alloc_failure;
397393 else {
394 OutputBuffer O(Buf, N);
398395 assert(Parser.ForwardTemplateRefs.empty());
399396 AST->print(O);
400397 O += '\0';
lib/libcxxabi/src/cxa_guard_impl.h+5-1
......@@ -5,6 +5,7 @@
55// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66//
77//===----------------------------------------------------------------------===//
8
89#ifndef LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H
910#define LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H
1011
......@@ -54,9 +55,12 @@
5455# endif
5556#endif
5657
58#include <__threading_support>
59#include <cstdint>
60#include <cstring>
5761#include <limits.h>
5862#include <stdlib.h>
59#include <__threading_support>
63
6064#ifndef _LIBCXXABI_HAS_NO_THREADS
6165# if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
6266# pragma comment(lib, "pthread")
lib/libcxxabi/src/demangle/ItaniumDemangle.h+26-6
......@@ -26,6 +26,7 @@
2626#include <cstdlib>
2727#include <cstring>
2828#include <limits>
29#include <new>
2930#include <utility>
3031
3132DEMANGLE_NAMESPACE_BEGIN
......@@ -369,6 +370,10 @@ public:
369370 VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_)
370371 : 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
372377 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
373378
374379 void printLeft(OutputBuffer &OB) const override {
......@@ -417,6 +422,9 @@ public:
417422 Child_->ArrayCache, Child_->FunctionCache),
418423 Quals(Quals_), Child(Child_) {}
419424
425 Qualifiers getQuals() const { return Quals; }
426 const Node *getChild() const { return Child; }
427
420428 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
421429
422430 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
......@@ -585,6 +593,8 @@ public:
585593 : Node(KPointerType, Pointee_->RHSComponentCache),
586594 Pointee(Pointee_) {}
587595
596 const Node *getPointee() const { return Pointee; }
597
588598 template<typename Fn> void match(Fn F) const { F(Pointee); }
589599
590600 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
......@@ -1070,6 +1080,9 @@ public:
10701080 VectorType(const Node *BaseType_, const Node *Dimension_)
10711081 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}
10721082
1083 const Node *getBaseType() const { return BaseType; }
1084 const Node *getDimension() const { return Dimension; }
1085
10731086 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
10741087
10751088 void printLeft(OutputBuffer &OB) const override {
......@@ -3019,14 +3032,21 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
30193032 if (numLeft() < 2)
30203033 return nullptr;
30213034
3022 auto Op = std::lower_bound(
3023 &Ops[0], &Ops[NumOps], First,
3024 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3025 if (Op == &Ops[NumOps] || *Op != First)
3035 // We can't use lower_bound as that can link to symbols in the C++ library,
3036 // and this must remain independant of that.
3037 size_t lower = 0u, upper = NumOps - 1; // Inclusive bounds.
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)
30263046 return nullptr;
30273047
30283048 First += 2;
3029 return Op;
3049 return &Ops[lower];
30303050}
30313051
30323052// <operator-name> ::= See parseOperatorEncoding()
......@@ -5099,7 +5119,7 @@ template <>
50995119struct FloatData<long double>
51005120{
51015121#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5102 defined(__wasm__) || defined(__riscv)
5122 defined(__wasm__) || defined(__riscv) || defined(__loongarch__)
51035123 static const size_t mangled_size = 32;
51045124#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
51055125 static const size_t mangled_size = 16;
lib/libcxxabi/src/demangle/Utility.h+3-22
......@@ -69,7 +69,9 @@ class OutputBuffer {
6969
7070public:
7171 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) {}
7375 OutputBuffer() = default;
7476 // Non-copyable
7577 OutputBuffer(const OutputBuffer &) = delete;
......@@ -77,12 +79,6 @@ public:
7779
7880 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
8682 /// If a ParameterPackExpansion (or similar type) is encountered, the offset
8783 /// into the pack that we're currently printing.
8884 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
......@@ -198,21 +194,6 @@ public:
198194 ScopedOverride &operator=(const ScopedOverride &) = delete;
199195};
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
216197DEMANGLE_NAMESPACE_END
217198
218199#endif
lib/libcxxabi/src/fallback_malloc.cpp+61-9
......@@ -15,6 +15,7 @@
1515#endif
1616#endif
1717
18#include <assert.h>
1819#include <stdlib.h> // for malloc, calloc, free
1920#include <string.h> // for memset
2021#include <new> // for std::__libcpp_aligned_{alloc,free}
......@@ -63,11 +64,28 @@ char heap[HEAP_SIZE] __attribute__((aligned));
6364typedef unsigned short heap_offset;
6465typedef 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
6670struct heap_node {
6771 heap_offset next_node; // offset into heap
6872 heap_size len; // size in units of "sizeof(heap_node)"
6973};
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
7189static const heap_node* list_end =
7290 (heap_node*)(&heap[HEAP_SIZE]); // one past the end of the heap
7391static heap_node* freelist = NULL;
......@@ -82,10 +100,23 @@ heap_offset offset_from_node(const heap_node* ptr) {
82100 sizeof(heap_node));
83101}
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
85116void init_heap() {
86 freelist = (heap_node*)heap;
117 freelist = getFirstAlignedNodeInHeap();
87118 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);
89120}
90121
91122// How big a chunk we allocate
......@@ -109,23 +140,44 @@ void* fallback_malloc(size_t len) {
109140 for (p = freelist, prev = 0; p && p != list_end;
110141 prev = p, p = node_from_offset(p->next_node)) {
111142
112 if (p->len > nelems) { // chunk is larger, shorten, and return the tail
113 heap_node* q;
143 // Check the invariant that all heap_nodes pointers 'p' are aligned
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);
116162 q = p + p->len;
117163 q->next_node = 0;
118 q->len = static_cast<heap_size>(nelems);
119 return (void*)(q + 1);
164 q->len = static_cast<heap_size>(aligned_nelems);
165 void* ptr = q + 1;
166 assert(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0);
167 return ptr;
120168 }
121169
122 if (p->len == nelems) { // exact size match
170 // 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) {
123173 if (prev == 0)
124174 freelist = node_from_offset(p->next_node);
125175 else
126176 prev->next_node = p->next_node;
127177 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;
129181 }
130182 }
131183 return NULL; // couldn't find a spot big enough