authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-01 16:36:40-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-01 16:39:29-07:00
logaa964bd555bf7d034b5bfea6275d6edddc35cb8c
tree13f5a2b3eb2704f6dfc85f26bbd0bddb07049a42
parentbd680139d084b673d1f56d0e63e01936c4680a91

update libcxxabi to llvm 14.0.6


31 files changed, 1169 insertions(+), 1185 deletions(-)

lib/libcxxabi/include/__cxxabi_config.h+2-2
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===-------------------------- __cxxabi_config.h -------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
...@@ -93,7 +93,7 @@...@@ -93,7 +93,7 @@
93# if !__has_feature(cxx_exceptions)93# if !__has_feature(cxx_exceptions)
94# define _LIBCXXABI_NO_EXCEPTIONS94# define _LIBCXXABI_NO_EXCEPTIONS
95# endif95# endif
96#elif defined(_LIBCXXABI_COMPILER_GCC) && !__EXCEPTIONS96#elif defined(_LIBCXXABI_COMPILER_GCC) && !defined(__EXCEPTIONS)
97# define _LIBCXXABI_NO_EXCEPTIONS97# define _LIBCXXABI_NO_EXCEPTIONS
98#endif98#endif
9999
lib/libcxxabi/include/cxxabi.h+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===--------------------------- cxxabi.h ---------------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/abort_message.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------- abort_message.cpp --------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/abort_message.h+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===-------------------------- abort_message.h-----------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_aux_runtime.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------ cxa_aux_runtime.cpp -------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_default_handlers.cpp+13-3
...@@ -1,11 +1,12 @@...@@ -1,11 +1,12 @@
1//===------------------------- cxa_default_handlers.cpp -------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//6//
7//7//
8// This file implements the default terminate_handler and unexpected_handler.8// This file implements the default terminate_handler, unexpected_handler and
9// new_handler.
9//===----------------------------------------------------------------------===//10//===----------------------------------------------------------------------===//
1011
11#include <exception>12#include <exception>
...@@ -15,7 +16,7 @@...@@ -15,7 +16,7 @@
15#include "cxa_handlers.h"16#include "cxa_handlers.h"
16#include "cxa_exception.h"17#include "cxa_exception.h"
17#include "private_typeinfo.h"18#include "private_typeinfo.h"
18#include "include/atomic_support.h"19#include "include/atomic_support.h" // from libc++
1920
20#if !defined(LIBCXXABI_SILENT_TERMINATE)21#if !defined(LIBCXXABI_SILENT_TERMINATE)
2122
...@@ -104,6 +105,9 @@ _LIBCPP_SAFE_STATIC std::terminate_handler __cxa_terminate_handler = default_ter...@@ -104,6 +105,9 @@ _LIBCPP_SAFE_STATIC std::terminate_handler __cxa_terminate_handler = default_ter
104_LIBCXXABI_DATA_VIS105_LIBCXXABI_DATA_VIS
105_LIBCPP_SAFE_STATIC std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler;106_LIBCPP_SAFE_STATIC std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler;
106107
108_LIBCXXABI_DATA_VIS
109_LIBCPP_SAFE_STATIC std::new_handler __cxa_new_handler = 0;
110
107namespace std111namespace std
108{112{
109113
...@@ -125,4 +129,10 @@ set_terminate(terminate_handler func) noexcept...@@ -125,4 +129,10 @@ set_terminate(terminate_handler func) noexcept
125 _AO_Acq_Rel);129 _AO_Acq_Rel);
126}130}
127131
132new_handler
133set_new_handler(new_handler handler) noexcept
134{
135 return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel);
136}
137
128}138}
lib/libcxxabi/src/cxa_demangle.cpp+7-7
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===-------------------------- cxa_demangle.cpp --------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
...@@ -342,21 +342,21 @@ __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {...@@ -342,21 +342,21 @@ __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {
342342
343 int InternalStatus = demangle_success;343 int InternalStatus = demangle_success;
344 Demangler Parser(MangledName, MangledName + std::strlen(MangledName));344 Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
345 OutputStream S;345 OutputBuffer O;
346346
347 Node *AST = Parser.parse();347 Node *AST = Parser.parse();
348348
349 if (AST == nullptr)349 if (AST == nullptr)
350 InternalStatus = demangle_invalid_mangled_name;350 InternalStatus = demangle_invalid_mangled_name;
351 else if (!initializeOutputStream(Buf, N, S, 1024))351 else if (!initializeOutputBuffer(Buf, N, O, 1024))
352 InternalStatus = demangle_memory_alloc_failure;352 InternalStatus = demangle_memory_alloc_failure;
353 else {353 else {
354 assert(Parser.ForwardTemplateRefs.empty());354 assert(Parser.ForwardTemplateRefs.empty());
355 AST->print(S);355 AST->print(O);
356 S += '\0';356 O += '\0';
357 if (N != nullptr)357 if (N != nullptr)
358 *N = S.getCurrentPosition();358 *N = O.getCurrentPosition();
359 Buf = S.getBuffer();359 Buf = O.getBuffer();
360 }360 }
361361
362 if (Status)362 if (Status)
lib/libcxxabi/src/cxa_exception.cpp+19-11
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------- cxa_exception.cpp --------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
...@@ -17,7 +17,7 @@...@@ -17,7 +17,7 @@
17#include "cxa_exception.h"17#include "cxa_exception.h"
18#include "cxa_handlers.h"18#include "cxa_handlers.h"
19#include "fallback_malloc.h"19#include "fallback_malloc.h"
20#include "include/atomic_support.h"20#include "include/atomic_support.h" // from libc++
2121
22#if __has_feature(address_sanitizer)22#if __has_feature(address_sanitizer)
23#include <sanitizer/asan_interface.h>23#include <sanitizer/asan_interface.h>
...@@ -341,8 +341,10 @@ unwinding with _Unwind_Resume....@@ -341,8 +341,10 @@ unwinding with _Unwind_Resume.
341According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any341According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any
342register, thus we have to write this function in assembly so that we can save342register, thus we have to write this function in assembly so that we can save
343{r1, r2, r3}. We don't have to save r0 because it is the return value and the343{r1, r2, r3}. We don't have to save r0 because it is the return value and the
344first argument to _Unwind_Resume(). In addition, we are saving r4 in order to344first argument to _Unwind_Resume(). In addition, we are saving lr in order to
345align the stack to 16 bytes, even though it is a callee-save register.345align the stack to 16 bytes and lr will be used to identify the caller and its
346frame information. _Unwind_Resume never return and we need to keep the original
347lr so just branch to it.
346*/348*/
347__attribute__((used)) static _Unwind_Exception *349__attribute__((used)) static _Unwind_Exception *
348__cxa_end_cleanup_impl()350__cxa_end_cleanup_impl()
...@@ -372,18 +374,24 @@ __cxa_end_cleanup_impl()...@@ -372,18 +374,24 @@ __cxa_end_cleanup_impl()
372 return &exception_header->unwindHeader;374 return &exception_header->unwindHeader;
373}375}
374376
375asm (377asm(" .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"
376 " .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"
377 " .globl __cxa_end_cleanup\n"378 " .globl __cxa_end_cleanup\n"
378 " .type __cxa_end_cleanup,%function\n"379 " .type __cxa_end_cleanup,%function\n"
379 "__cxa_end_cleanup:\n"380 "__cxa_end_cleanup:\n"
380 " push {r1, r2, r3, r4}\n"381#if defined(__ARM_FEATURE_BTI_DEFAULT)
382 " bti\n"
383#endif
384 " push {r1, r2, r3, lr}\n"
381 " bl __cxa_end_cleanup_impl\n"385 " bl __cxa_end_cleanup_impl\n"
382 " pop {r1, r2, r3, r4}\n"386 " pop {r1, r2, r3, r4}\n"
383 " bl _Unwind_Resume\n"387 " mov lr, r4\n"
384 " bl abort\n"388#if defined(LIBCXXABI_BAREMETAL)
385 " .popsection"389 " ldr r4, =_Unwind_Resume\n"
386);390 " bx r4\n"
391#else
392 " b _Unwind_Resume\n"
393#endif
394 " .popsection");
387#endif // defined(_LIBCXXABI_ARM_EHABI)395#endif // defined(_LIBCXXABI_ARM_EHABI)
388396
389/*397/*
lib/libcxxabi/src/cxa_exception.h+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------- cxa_exception.h ----------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_exception_storage.cpp+34-36
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===--------------------- cxa_exception_storage.cpp ----------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
...@@ -21,25 +21,24 @@ extern "C" {...@@ -21,25 +21,24 @@ extern "C" {
21 static __cxa_eh_globals eh_globals;21 static __cxa_eh_globals eh_globals;
22 __cxa_eh_globals *__cxa_get_globals() { return &eh_globals; }22 __cxa_eh_globals *__cxa_get_globals() { return &eh_globals; }
23 __cxa_eh_globals *__cxa_get_globals_fast() { return &eh_globals; }23 __cxa_eh_globals *__cxa_get_globals_fast() { return &eh_globals; }
24 }24} // extern "C"
25}25} // namespace __cxxabiv1
2626
27#elif defined(HAS_THREAD_LOCAL)27#elif defined(HAS_THREAD_LOCAL)
2828
29namespace __cxxabiv1 {29namespace __cxxabiv1 {
30
31namespace {30namespace {
32 __cxa_eh_globals * __globals () {31 __cxa_eh_globals *__globals() {
33 static thread_local __cxa_eh_globals eh_globals;32 static thread_local __cxa_eh_globals eh_globals;
34 return &eh_globals;33 return &eh_globals;
35 }
36 }34 }
35} // namespace
3736
38extern "C" {37extern "C" {
39 __cxa_eh_globals * __cxa_get_globals () { return __globals (); }38 __cxa_eh_globals *__cxa_get_globals() { return __globals(); }
40 __cxa_eh_globals * __cxa_get_globals_fast () { return __globals (); }39 __cxa_eh_globals *__cxa_get_globals_fast() { return __globals(); }
41 }40} // extern "C"
42}41} // namespace __cxxabiv1
4342
44#else43#else
4544
...@@ -59,47 +58,46 @@ namespace {...@@ -59,47 +58,46 @@ namespace {
59 std::__libcpp_tls_key key_;58 std::__libcpp_tls_key key_;
60 std::__libcpp_exec_once_flag flag_ = _LIBCPP_EXEC_ONCE_INITIALIZER;59 std::__libcpp_exec_once_flag flag_ = _LIBCPP_EXEC_ONCE_INITIALIZER;
6160
62 void _LIBCPP_TLS_DESTRUCTOR_CC destruct_ (void *p) {61 void _LIBCPP_TLS_DESTRUCTOR_CC destruct_(void *p) {
63 __free_with_fallback ( p );62 __free_with_fallback(p);
64 if ( 0 != std::__libcpp_tls_set ( key_, NULL ) )63 if (0 != std::__libcpp_tls_set(key_, NULL))
65 abort_message("cannot zero out thread value for __cxa_get_globals()");64 abort_message("cannot zero out thread value for __cxa_get_globals()");
66 }65 }
6766
68 void construct_ () {67 void construct_() {
69 if ( 0 != std::__libcpp_tls_create ( &key_, destruct_ ) )68 if (0 != std::__libcpp_tls_create(&key_, destruct_))
70 abort_message("cannot create thread specific key for __cxa_get_globals()");69 abort_message("cannot create thread specific key for __cxa_get_globals()");
71 }70 }
72}71} // namespace
7372
74extern "C" {73extern "C" {
75 __cxa_eh_globals * __cxa_get_globals () {74 __cxa_eh_globals *__cxa_get_globals() {
76 // Try to get the globals for this thread75 // Try to get the globals for this thread
77 __cxa_eh_globals* retVal = __cxa_get_globals_fast ();76 __cxa_eh_globals *retVal = __cxa_get_globals_fast();
7877
79 // If this is the first time we've been asked for these globals, create them78 // If this is the first time we've been asked for these globals, create them
80 if ( NULL == retVal ) {79 if (NULL == retVal) {
81 retVal = static_cast<__cxa_eh_globals*>80 retVal = static_cast<__cxa_eh_globals*>(
82 (__calloc_with_fallback (1, sizeof (__cxa_eh_globals)));81 __calloc_with_fallback(1, sizeof(__cxa_eh_globals)));
83 if ( NULL == retVal )82 if (NULL == retVal)
84 abort_message("cannot allocate __cxa_eh_globals");83 abort_message("cannot allocate __cxa_eh_globals");
85 if ( 0 != std::__libcpp_tls_set ( key_, retVal ) )84 if (0 != std::__libcpp_tls_set(key_, retVal))
86 abort_message("std::__libcpp_tls_set failure in __cxa_get_globals()");85 abort_message("std::__libcpp_tls_set failure in __cxa_get_globals()");
87 }
88 return retVal;
89 }86 }
87 return retVal;
88 }
9089
91 // Note that this implementation will reliably return NULL if not90 // Note that this implementation will reliably return NULL if not
92 // preceded by a call to __cxa_get_globals(). This is an extension91 // preceded by a call to __cxa_get_globals(). This is an extension
93 // to the Itanium ABI and is taken advantage of in several places in92 // to the Itanium ABI and is taken advantage of in several places in
94 // libc++abi.93 // libc++abi.
95 __cxa_eh_globals * __cxa_get_globals_fast () {94 __cxa_eh_globals *__cxa_get_globals_fast() {
96 // First time through, create the key.95 // First time through, create the key.
97 if (0 != std::__libcpp_execute_once(&flag_, construct_))96 if (0 != std::__libcpp_execute_once(&flag_, construct_))
98 abort_message("execute once failure in __cxa_get_globals_fast()");97 abort_message("execute once failure in __cxa_get_globals_fast()");
99// static int init = construct_();
100 return static_cast<__cxa_eh_globals*>(std::__libcpp_tls_get(key_));98 return static_cast<__cxa_eh_globals*>(std::__libcpp_tls_get(key_));
101 }99 }
100} // extern "C"
101} // namespace __cxxabiv1
102102
103}
104}
105#endif103#endif
lib/libcxxabi/src/cxa_guard.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===---------------------------- cxa_guard.cpp ---------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_guard_impl.h+260-182
...@@ -23,9 +23,15 @@...@@ -23,9 +23,15 @@
23 * the thread currently performing initialization is stored in the second word.23 * the thread currently performing initialization is stored in the second word.
24 *24 *
25 * Guard Object Layout:25 * Guard Object Layout:
26 * -------------------------------------------------------------------------26 * ---------------------------------------------------------------------------
27 * |a: guard byte | a+1: init byte | a+2 : unused ... | a+4: thread-id ... |27 * | a+0: guard byte | a+1: init byte | a+2: unused ... | a+4: thread-id ... |
28 * ------------------------------------------------------------------------28 * ---------------------------------------------------------------------------
29 *
30 * Note that we don't do what the ABI docs suggest (put a mutex in the guard
31 * object which we acquire in cxa_guard_acquire and release in
32 * cxa_guard_release). Instead we use the init byte to imitate that behaviour,
33 * but without actually holding anything mutex related between aquire and
34 * release/abort.
29 *35 *
30 * Access Protocol:36 * Access Protocol:
31 * For each implementation the guard byte is checked and set before accessing37 * For each implementation the guard byte is checked and set before accessing
...@@ -38,28 +44,31 @@...@@ -38,28 +44,31 @@
38 */44 */
3945
40#include "__cxxabi_config.h"46#include "__cxxabi_config.h"
41#include "include/atomic_support.h"47#include "include/atomic_support.h" // from libc++
42#include <unistd.h>
43#if defined(__has_include)48#if defined(__has_include)
44# if __has_include(<sys/syscall.h>)49# if __has_include(<sys/syscall.h>)
45# include <sys/syscall.h>50# include <sys/syscall.h>
46# endif51# endif
52# if __has_include(<unistd.h>)
53# include <unistd.h>
54# endif
47#endif55#endif
4856
57#include <limits.h>
49#include <stdlib.h>58#include <stdlib.h>
50#include <__threading_support>59#include <__threading_support>
51#ifndef _LIBCXXABI_HAS_NO_THREADS60#ifndef _LIBCXXABI_HAS_NO_THREADS
52#if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)61# if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
53#pragma comment(lib, "pthread")62# pragma comment(lib, "pthread")
54#endif63# endif
55#endif64#endif
5665
57#if defined(__clang__)66#if defined(__clang__)
58# pragma clang diagnostic push67# pragma clang diagnostic push
59# pragma clang diagnostic ignored "-Wtautological-pointer-compare"68# pragma clang diagnostic ignored "-Wtautological-pointer-compare"
60#elif defined(__GNUC__)69#elif defined(__GNUC__)
61# pragma GCC diagnostic push70# pragma GCC diagnostic push
62# pragma GCC diagnostic ignored "-Waddress"71# pragma GCC diagnostic ignored "-Waddress"
63#endif72#endif
6473
65// To make testing possible, this header is included from both cxa_guard.cpp74// To make testing possible, this header is included from both cxa_guard.cpp
...@@ -74,20 +83,20 @@...@@ -74,20 +83,20 @@
74// defined when including this file. Only `src/cxa_guard.cpp` should define83// defined when including this file. Only `src/cxa_guard.cpp` should define
75// the former.84// the former.
76#ifdef BUILDING_CXA_GUARD85#ifdef BUILDING_CXA_GUARD
77# include "abort_message.h"86# include "abort_message.h"
78# define ABORT_WITH_MESSAGE(...) ::abort_message(__VA_ARGS__)87# define ABORT_WITH_MESSAGE(...) ::abort_message(__VA_ARGS__)
79#elif defined(TESTING_CXA_GUARD)88#elif defined(TESTING_CXA_GUARD)
80# define ABORT_WITH_MESSAGE(...) ::abort()89# define ABORT_WITH_MESSAGE(...) ::abort()
81#else90#else
82# error "Either BUILDING_CXA_GUARD or TESTING_CXA_GUARD must be defined"91# error "Either BUILDING_CXA_GUARD or TESTING_CXA_GUARD must be defined"
83#endif92#endif
8493
85#if __has_feature(thread_sanitizer)94#if __has_feature(thread_sanitizer)
86extern "C" void __tsan_acquire(void*);95extern "C" void __tsan_acquire(void*);
87extern "C" void __tsan_release(void*);96extern "C" void __tsan_release(void*);
88#else97#else
89#define __tsan_acquire(addr) ((void)0)98# define __tsan_acquire(addr) ((void)0)
90#define __tsan_release(addr) ((void)0)99# define __tsan_release(addr) ((void)0)
91#endif100#endif
92101
93namespace __cxxabiv1 {102namespace __cxxabiv1 {
...@@ -99,7 +108,7 @@ namespace {...@@ -99,7 +108,7 @@ namespace {
99// Misc Utilities108// Misc Utilities
100//===----------------------------------------------------------------------===//109//===----------------------------------------------------------------------===//
101110
102template <class T, T(*Init)()>111template <class T, T (*Init)()>
103struct LazyValue {112struct LazyValue {
104 LazyValue() : is_init(false) {}113 LazyValue() : is_init(false) {}
105114
...@@ -110,7 +119,8 @@ struct LazyValue {...@@ -110,7 +119,8 @@ struct LazyValue {
110 }119 }
111 return value;120 return value;
112 }121 }
113 private:122
123private:
114 T value;124 T value;
115 bool is_init = false;125 bool is_init = false;
116};126};
...@@ -120,25 +130,19 @@ class AtomicInt {...@@ -120,25 +130,19 @@ class AtomicInt {
120public:130public:
121 using MemoryOrder = std::__libcpp_atomic_order;131 using MemoryOrder = std::__libcpp_atomic_order;
122132
123 explicit AtomicInt(IntType *b) : b_(b) {}133 explicit AtomicInt(IntType* b) : b_(b) {}
124 AtomicInt(AtomicInt const&) = delete;134 AtomicInt(AtomicInt const&) = delete;
125 AtomicInt& operator=(AtomicInt const&) = delete;135 AtomicInt& operator=(AtomicInt const&) = delete;
126136
127 IntType load(MemoryOrder ord) {137 IntType load(MemoryOrder ord) { return std::__libcpp_atomic_load(b_, ord); }
128 return std::__libcpp_atomic_load(b_, ord);138 void store(IntType val, MemoryOrder ord) { std::__libcpp_atomic_store(b_, val, ord); }
129 }139 IntType exchange(IntType new_val, MemoryOrder ord) { return std::__libcpp_atomic_exchange(b_, new_val, ord); }
130 void store(IntType val, MemoryOrder ord) {140 bool compare_exchange(IntType* expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
131 std::__libcpp_atomic_store(b_, val, ord);
132 }
133 IntType exchange(IntType new_val, MemoryOrder ord) {
134 return std::__libcpp_atomic_exchange(b_, new_val, ord);
135 }
136 bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
137 return std::__libcpp_atomic_compare_exchange(b_, expected, desired, ord_success, ord_failure);141 return std::__libcpp_atomic_compare_exchange(b_, expected, desired, ord_success, ord_failure);
138 }142 }
139143
140private:144private:
141 IntType *b_;145 IntType* b_;
142};146};
143147
144//===----------------------------------------------------------------------===//148//===----------------------------------------------------------------------===//
...@@ -148,8 +152,7 @@ private:...@@ -148,8 +152,7 @@ private:
148#if defined(__APPLE__) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD)152#if defined(__APPLE__) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
149uint32_t PlatformThreadID() {153uint32_t PlatformThreadID() {
150 static_assert(sizeof(mach_port_t) == sizeof(uint32_t), "");154 static_assert(sizeof(mach_port_t) == sizeof(uint32_t), "");
151 return static_cast<uint32_t>(155 return static_cast<uint32_t>(pthread_mach_thread_np(std::__libcpp_thread_get_current_id()));
152 pthread_mach_thread_np(std::__libcpp_thread_get_current_id()));
153}156}
154#elif defined(SYS_gettid) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD)157#elif defined(SYS_gettid) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
155uint32_t PlatformThreadID() {158uint32_t PlatformThreadID() {
...@@ -160,99 +163,108 @@ uint32_t PlatformThreadID() {...@@ -160,99 +163,108 @@ uint32_t PlatformThreadID() {
160constexpr uint32_t (*PlatformThreadID)() = nullptr;163constexpr uint32_t (*PlatformThreadID)() = nullptr;
161#endif164#endif
162165
163
164constexpr bool PlatformSupportsThreadID() {
165 return +PlatformThreadID != nullptr;
166}
167
168//===----------------------------------------------------------------------===//166//===----------------------------------------------------------------------===//
169// GuardBase167// GuardByte
170//===----------------------------------------------------------------------===//168//===----------------------------------------------------------------------===//
171169
172enum class AcquireResult {
173 INIT_IS_DONE,
174 INIT_IS_PENDING,
175};
176constexpr AcquireResult INIT_IS_DONE = AcquireResult::INIT_IS_DONE;
177constexpr AcquireResult INIT_IS_PENDING = AcquireResult::INIT_IS_PENDING;
178
179static constexpr uint8_t UNSET = 0;170static constexpr uint8_t UNSET = 0;
180static constexpr uint8_t COMPLETE_BIT = (1 << 0);171static constexpr uint8_t COMPLETE_BIT = (1 << 0);
181static constexpr uint8_t PENDING_BIT = (1 << 1);172static constexpr uint8_t PENDING_BIT = (1 << 1);
182static constexpr uint8_t WAITING_BIT = (1 << 2);173static constexpr uint8_t WAITING_BIT = (1 << 2);
183174
184template <class Derived>175/// Manages reads and writes to the guard byte.
185struct GuardObject {176struct GuardByte {
186 GuardObject() = delete;177 GuardByte() = delete;
187 GuardObject(GuardObject const&) = delete;178 GuardByte(GuardByte const&) = delete;
188 GuardObject& operator=(GuardObject const&) = delete;179 GuardByte& operator=(GuardByte const&) = delete;
189180
190 explicit GuardObject(uint32_t* g)181 explicit GuardByte(uint8_t* const guard_byte_address) : guard_byte(guard_byte_address) {}
191 : base_address(g), guard_byte_address(reinterpret_cast<uint8_t*>(g)),
192 init_byte_address(reinterpret_cast<uint8_t*>(g) + 1),
193 thread_id_address(nullptr) {}
194
195 explicit GuardObject(uint64_t* g)
196 : base_address(g), guard_byte_address(reinterpret_cast<uint8_t*>(g)),
197 init_byte_address(reinterpret_cast<uint8_t*>(g) + 1),
198 thread_id_address(reinterpret_cast<uint32_t*>(g) + 1) {}
199182
200public:183public:
201 /// Implements __cxa_guard_acquire184 /// The guard byte portion of cxa_guard_acquire. Returns true if
202 AcquireResult cxa_guard_acquire() {185 /// initialization has already been completed.
203 AtomicInt<uint8_t> guard_byte(guard_byte_address);186 bool acquire() {
204 if (guard_byte.load(std::_AO_Acquire) != UNSET)187 // if guard_byte is non-zero, we have already completed initialization
205 return INIT_IS_DONE;188 // (i.e. release has been called)
206 return derived()->acquire_init_byte();189 return guard_byte.load(std::_AO_Acquire) != UNSET;
207 }
208
209 /// Implements __cxa_guard_release
210 void cxa_guard_release() {
211 AtomicInt<uint8_t> guard_byte(guard_byte_address);
212 // Store complete first, so that when release wakes other folks, they see
213 // it as having been completed.
214 guard_byte.store(COMPLETE_BIT, std::_AO_Release);
215 derived()->release_init_byte();
216 }190 }
217191
218 /// Implements __cxa_guard_abort192 /// The guard byte portion of cxa_guard_release.
219 void cxa_guard_abort() { derived()->abort_init_byte(); }193 void release() { guard_byte.store(COMPLETE_BIT, std::_AO_Release); }
220194
221public:195 /// The guard byte portion of cxa_guard_abort.
222 /// base_address - the address of the original guard object.196 void abort() {} // Nothing to do
223 void* const base_address;
224 /// The address of the guard byte at offset 0.
225 uint8_t* const guard_byte_address;
226 /// The address of the byte used by the implementation during initialization.
227 uint8_t* const init_byte_address;
228 /// An optional address storing an identifier for the thread performing initialization.
229 /// It's used to detect recursive initialization.
230 uint32_t* const thread_id_address;
231197
232private:198private:
233 Derived* derived() { return static_cast<Derived*>(this); }199 AtomicInt<uint8_t> guard_byte;
234};200};
235201
202//===----------------------------------------------------------------------===//
203// InitByte Implementations
204//===----------------------------------------------------------------------===//
205//
206// Each initialization byte implementation supports the following methods:
207//
208// InitByte(uint8_t* _init_byte_address, uint32_t* _thread_id_address)
209// Construct the InitByte object, initializing our member variables
210//
211// bool acquire()
212// Called before we start the initialization. Check if someone else has already started, and if
213// not to signal our intent to start it ourselves. We determine the current status from the init
214// byte, which is one of 4 possible values:
215// COMPLETE: Initialization was finished by somebody else. Return true.
216// PENDING: Somebody has started the initialization already, set the WAITING bit,
217// then wait for the init byte to get updated with a new value.
218// (PENDING|WAITING): Somebody has started the initialization already, and we're not the
219// first one waiting. Wait for the init byte to get updated.
220// UNSET: Initialization hasn't successfully completed, and nobody is currently
221// performing the initialization. Set the PENDING bit to indicate our
222// intention to start the initialization, and return false.
223// The return value indicates whether initialization has already been completed.
224//
225// void release()
226// Called after successfully completing the initialization. Update the init byte to reflect
227// that, then if anybody else is waiting, wake them up.
228//
229// void abort()
230// Called after an error is thrown during the initialization. Reset the init byte to UNSET to
231// indicate that we're no longer performing the initialization, then if anybody is waiting, wake
232// them up so they can try performing the initialization.
233//
234
236//===----------------------------------------------------------------------===//235//===----------------------------------------------------------------------===//
237// Single Threaded Implementation236// Single Threaded Implementation
238//===----------------------------------------------------------------------===//237//===----------------------------------------------------------------------===//
239238
240struct InitByteNoThreads : GuardObject<InitByteNoThreads> {239/// InitByteNoThreads - Doesn't use any inter-thread synchronization when
241 using GuardObject::GuardObject;240/// managing reads and writes to the init byte.
241struct InitByteNoThreads {
242 InitByteNoThreads() = delete;
243 InitByteNoThreads(InitByteNoThreads const&) = delete;
244 InitByteNoThreads& operator=(InitByteNoThreads const&) = delete;
242245
243 AcquireResult acquire_init_byte() {246 explicit InitByteNoThreads(uint8_t* _init_byte_address, uint32_t*) : init_byte_address(_init_byte_address) {}
247
248 /// The init byte portion of cxa_guard_acquire. Returns true if
249 /// initialization has already been completed.
250 bool acquire() {
244 if (*init_byte_address == COMPLETE_BIT)251 if (*init_byte_address == COMPLETE_BIT)
245 return INIT_IS_DONE;252 return true;
246 if (*init_byte_address & PENDING_BIT)253 if (*init_byte_address & PENDING_BIT)
247 ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization");254 ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization");
248 *init_byte_address = PENDING_BIT;255 *init_byte_address = PENDING_BIT;
249 return INIT_IS_PENDING;256 return false;
250 }257 }
251258
252 void release_init_byte() { *init_byte_address = COMPLETE_BIT; }259 /// The init byte portion of cxa_guard_release.
253 void abort_init_byte() { *init_byte_address = UNSET; }260 void release() { *init_byte_address = COMPLETE_BIT; }
254};261 /// The init byte portion of cxa_guard_abort.
262 void abort() { *init_byte_address = UNSET; }
255263
264private:
265 /// The address of the byte used during initialization.
266 uint8_t* const init_byte_address;
267};
256268
257//===----------------------------------------------------------------------===//269//===----------------------------------------------------------------------===//
258// Global Mutex Implementation270// Global Mutex Implementation
...@@ -280,9 +292,7 @@ struct LibcppCondVar {...@@ -280,9 +292,7 @@ struct LibcppCondVar {
280 LibcppCondVar(LibcppCondVar const&) = delete;292 LibcppCondVar(LibcppCondVar const&) = delete;
281 LibcppCondVar& operator=(LibcppCondVar const&) = delete;293 LibcppCondVar& operator=(LibcppCondVar const&) = delete;
282294
283 bool wait(LibcppMutex& mut) {295 bool wait(LibcppMutex& mut) { return std::__libcpp_condvar_wait(&cond, &mut.mutex); }
284 return std::__libcpp_condvar_wait(&cond, &mut.mutex);
285 }
286 bool broadcast() { return std::__libcpp_condvar_broadcast(&cond); }296 bool broadcast() { return std::__libcpp_condvar_broadcast(&cond); }
287297
288private:298private:
...@@ -293,28 +303,25 @@ struct LibcppMutex {};...@@ -293,28 +303,25 @@ struct LibcppMutex {};
293struct LibcppCondVar {};303struct LibcppCondVar {};
294#endif // !defined(_LIBCXXABI_HAS_NO_THREADS)304#endif // !defined(_LIBCXXABI_HAS_NO_THREADS)
295305
296306/// InitByteGlobalMutex - Uses a global mutex and condition variable (common to
307/// all static local variables) to manage reads and writes to the init byte.
297template <class Mutex, class CondVar, Mutex& global_mutex, CondVar& global_cond,308template <class Mutex, class CondVar, Mutex& global_mutex, CondVar& global_cond,
298 uint32_t (*GetThreadID)() = PlatformThreadID>309 uint32_t (*GetThreadID)() = PlatformThreadID>
299struct InitByteGlobalMutex310struct InitByteGlobalMutex {
300 : GuardObject<InitByteGlobalMutex<Mutex, CondVar, global_mutex, global_cond,
301 GetThreadID>> {
302
303 using BaseT = typename InitByteGlobalMutex::GuardObject;
304 using BaseT::BaseT;
305311
306 explicit InitByteGlobalMutex(uint32_t *g)312 explicit InitByteGlobalMutex(uint8_t* _init_byte_address, uint32_t* _thread_id_address)
307 : BaseT(g), has_thread_id_support(false) {}313 : init_byte_address(_init_byte_address), thread_id_address(_thread_id_address),
308 explicit InitByteGlobalMutex(uint64_t *g)314 has_thread_id_support(_thread_id_address != nullptr && GetThreadID != nullptr) {}
309 : BaseT(g), has_thread_id_support(PlatformSupportsThreadID()) {}
310315
311public:316public:
312 AcquireResult acquire_init_byte() {317 /// The init byte portion of cxa_guard_acquire. Returns true if
318 /// initialization has already been completed.
319 bool acquire() {
313 LockGuard g("__cxa_guard_acquire");320 LockGuard g("__cxa_guard_acquire");
314 // Check for possible recursive initialization.321 // Check for possible recursive initialization.
315 if (has_thread_id_support && (*init_byte_address & PENDING_BIT)) {322 if (has_thread_id_support && (*init_byte_address & PENDING_BIT)) {
316 if (*thread_id_address == current_thread_id.get())323 if (*thread_id_address == current_thread_id.get())
317 ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization");324 ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization");
318 }325 }
319326
320 // Wait until the pending bit is not set.327 // Wait until the pending bit is not set.
...@@ -324,16 +331,17 @@ public:...@@ -324,16 +331,17 @@ public:
324 }331 }
325332
326 if (*init_byte_address == COMPLETE_BIT)333 if (*init_byte_address == COMPLETE_BIT)
327 return INIT_IS_DONE;334 return true;
328335
329 if (has_thread_id_support)336 if (has_thread_id_support)
330 *thread_id_address = current_thread_id.get();337 *thread_id_address = current_thread_id.get();
331338
332 *init_byte_address = PENDING_BIT;339 *init_byte_address = PENDING_BIT;
333 return INIT_IS_PENDING;340 return false;
334 }341 }
335342
336 void release_init_byte() {343 /// The init byte portion of cxa_guard_release.
344 void release() {
337 bool has_waiting;345 bool has_waiting;
338 {346 {
339 LockGuard g("__cxa_guard_release");347 LockGuard g("__cxa_guard_release");
...@@ -347,7 +355,8 @@ public:...@@ -347,7 +355,8 @@ public:
347 }355 }
348 }356 }
349357
350 void abort_init_byte() {358 /// The init byte portion of cxa_guard_abort.
359 void abort() {
351 bool has_waiting;360 bool has_waiting;
352 {361 {
353 LockGuard g("__cxa_guard_abort");362 LockGuard g("__cxa_guard_abort");
...@@ -364,8 +373,12 @@ public:...@@ -364,8 +373,12 @@ public:
364 }373 }
365374
366private:375private:
367 using BaseT::init_byte_address;376 /// The address of the byte used during initialization.
368 using BaseT::thread_id_address;377 uint8_t* const init_byte_address;
378 /// An optional address storing an identifier for the thread performing initialization.
379 /// It's used to detect recursive initialization.
380 uint32_t* const thread_id_address;
381
369 const bool has_thread_id_support;382 const bool has_thread_id_support;
370 LazyValue<uint32_t, GetThreadID> current_thread_id;383 LazyValue<uint32_t, GetThreadID> current_thread_id;
371384
...@@ -375,8 +388,7 @@ private:...@@ -375,8 +388,7 @@ private:
375 LockGuard(LockGuard const&) = delete;388 LockGuard(LockGuard const&) = delete;
376 LockGuard& operator=(LockGuard const&) = delete;389 LockGuard& operator=(LockGuard const&) = delete;
377390
378 explicit LockGuard(const char* calling_func)391 explicit LockGuard(const char* calling_func) : calling_func_(calling_func) {
379 : calling_func_(calling_func) {
380 if (global_mutex.lock())392 if (global_mutex.lock())
381 ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func_);393 ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func_);
382 }394 }
...@@ -411,50 +423,40 @@ constexpr void (*PlatformFutexWait)(int*, int) = nullptr;...@@ -411,50 +423,40 @@ constexpr void (*PlatformFutexWait)(int*, int) = nullptr;
411constexpr void (*PlatformFutexWake)(int*) = nullptr;423constexpr void (*PlatformFutexWake)(int*) = nullptr;
412#endif424#endif
413425
414constexpr bool PlatformSupportsFutex() {426constexpr bool PlatformSupportsFutex() { return +PlatformFutexWait != nullptr; }
415 return +PlatformFutexWait != nullptr;
416}
417427
418/// InitByteFutex - Manages initialization using atomics and the futex syscall428/// InitByteFutex - Uses a futex to manage reads and writes to the init byte.
419/// for waiting and waking.429template <void (*Wait)(int*, int) = PlatformFutexWait, void (*Wake)(int*) = PlatformFutexWake,
420template <void (*Wait)(int*, int) = PlatformFutexWait,
421 void (*Wake)(int*) = PlatformFutexWake,
422 uint32_t (*GetThreadIDArg)() = PlatformThreadID>430 uint32_t (*GetThreadIDArg)() = PlatformThreadID>
423struct InitByteFutex : GuardObject<InitByteFutex<Wait, Wake, GetThreadIDArg>> {431struct InitByteFutex {
424 using BaseT = typename InitByteFutex::GuardObject;
425
426 /// ARM Constructor
427 explicit InitByteFutex(uint32_t *g) : BaseT(g),
428 init_byte(this->init_byte_address),
429 has_thread_id_support(this->thread_id_address && GetThreadIDArg),
430 thread_id(this->thread_id_address) {}
431432
432 /// Itanium Constructor433 explicit InitByteFutex(uint8_t* _init_byte_address, uint32_t* _thread_id_address)
433 explicit InitByteFutex(uint64_t *g) : BaseT(g),434 : init_byte(_init_byte_address),
434 init_byte(this->init_byte_address),435 has_thread_id_support(_thread_id_address != nullptr && GetThreadIDArg != nullptr),
435 has_thread_id_support(this->thread_id_address && GetThreadIDArg),436 thread_id(_thread_id_address),
436 thread_id(this->thread_id_address) {}437 base_address(reinterpret_cast<int*>(/*_init_byte_address & ~0x3*/ _init_byte_address - 1)) {}
437438
438public:439public:
439 AcquireResult acquire_init_byte() {440 /// The init byte portion of cxa_guard_acquire. Returns true if
441 /// initialization has already been completed.
442 bool acquire() {
440 while (true) {443 while (true) {
441 uint8_t last_val = UNSET;444 uint8_t last_val = UNSET;
442 if (init_byte.compare_exchange(&last_val, PENDING_BIT, std::_AO_Acq_Rel,445 if (init_byte.compare_exchange(&last_val, PENDING_BIT, std::_AO_Acq_Rel, std::_AO_Acquire)) {
443 std::_AO_Acquire)) {
444 if (has_thread_id_support) {446 if (has_thread_id_support) {
445 thread_id.store(current_thread_id.get(), std::_AO_Relaxed);447 thread_id.store(current_thread_id.get(), std::_AO_Relaxed);
446 }448 }
447 return INIT_IS_PENDING;449 return false;
448 }450 }
449451
450 if (last_val == COMPLETE_BIT)452 if (last_val == COMPLETE_BIT)
451 return INIT_IS_DONE;453 return true;
452454
453 if (last_val & PENDING_BIT) {455 if (last_val & PENDING_BIT) {
454456
455 // Check for recursive initialization457 // Check for recursive initialization
456 if (has_thread_id_support && thread_id.load(std::_AO_Relaxed) == current_thread_id.get()) {458 if (has_thread_id_support && thread_id.load(std::_AO_Relaxed) == current_thread_id.get()) {
457 ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization");459 ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization");
458 }460 }
459461
460 if ((last_val & WAITING_BIT) == 0) {462 if ((last_val & WAITING_BIT) == 0) {
...@@ -462,11 +464,10 @@ public:...@@ -462,11 +464,10 @@ public:
462 // (1) another thread finished the whole thing before we got here464 // (1) another thread finished the whole thing before we got here
463 // (2) another thread set the waiting bit we were trying to thread465 // (2) another thread set the waiting bit we were trying to thread
464 // (3) another thread had an exception and failed to finish466 // (3) another thread had an exception and failed to finish
465 if (!init_byte.compare_exchange(&last_val, PENDING_BIT | WAITING_BIT,467 if (!init_byte.compare_exchange(&last_val, PENDING_BIT | WAITING_BIT, std::_AO_Acq_Rel, std::_AO_Release)) {
466 std::_AO_Acq_Rel, std::_AO_Release)) {
467 // (1) success, via someone else's work!468 // (1) success, via someone else's work!
468 if (last_val == COMPLETE_BIT)469 if (last_val == COMPLETE_BIT)
469 return INIT_IS_DONE;470 return true;
470471
471 // (3) someone else, bailed on doing the work, retry from the start!472 // (3) someone else, bailed on doing the work, retry from the start!
472 if (last_val == UNSET)473 if (last_val == UNSET)
...@@ -480,30 +481,30 @@ public:...@@ -480,30 +481,30 @@ public:
480 }481 }
481 }482 }
482483
483 void release_init_byte() {484 /// The init byte portion of cxa_guard_release.
485 void release() {
484 uint8_t old = init_byte.exchange(COMPLETE_BIT, std::_AO_Acq_Rel);486 uint8_t old = init_byte.exchange(COMPLETE_BIT, std::_AO_Acq_Rel);
485 if (old & WAITING_BIT)487 if (old & WAITING_BIT)
486 wake_all();488 wake_all();
487 }489 }
488490
489 void abort_init_byte() {491 /// The init byte portion of cxa_guard_abort.
492 void abort() {
490 if (has_thread_id_support)493 if (has_thread_id_support)
491 thread_id.store(0, std::_AO_Relaxed);494 thread_id.store(0, std::_AO_Relaxed);
492495
493 uint8_t old = init_byte.exchange(0, std::_AO_Acq_Rel);496 uint8_t old = init_byte.exchange(UNSET, std::_AO_Acq_Rel);
494 if (old & WAITING_BIT)497 if (old & WAITING_BIT)
495 wake_all();498 wake_all();
496 }499 }
497500
498private:501private:
499 /// Use the futex to wait on the current guard variable. Futex expects a502 /// Use the futex to wait on the current guard variable. Futex expects a
500 /// 32-bit 4-byte aligned address as the first argument, so we have to use use503 /// 32-bit 4-byte aligned address as the first argument, so we use the 4-byte
501 /// the base address of the guard variable (not the init byte).504 /// aligned address that encompasses the init byte (i.e. the address of the
502 void wait_on_initialization() {505 /// raw guard object that was passed to __cxa_guard_acquire/release/abort).
503 Wait(static_cast<int*>(this->base_address),506 void wait_on_initialization() { Wait(base_address, expected_value_for_futex(PENDING_BIT | WAITING_BIT)); }
504 expected_value_for_futex(PENDING_BIT | WAITING_BIT));507 void wake_all() { Wake(base_address); }
505 }
506 void wake_all() { Wake(static_cast<int*>(this->base_address)); }
507508
508private:509private:
509 AtomicInt<uint8_t> init_byte;510 AtomicInt<uint8_t> init_byte;
...@@ -513,6 +514,10 @@ private:...@@ -513,6 +514,10 @@ private:
513 AtomicInt<uint32_t> thread_id;514 AtomicInt<uint32_t> thread_id;
514 LazyValue<uint32_t, GetThreadIDArg> current_thread_id;515 LazyValue<uint32_t, GetThreadIDArg> current_thread_id;
515516
517 /// the 4-byte-aligned address that encompasses the init byte (i.e. the
518 /// address of the raw guard object).
519 int* const base_address;
520
516 /// Create the expected integer value for futex `wait(int* addr, int expected)`.521 /// Create the expected integer value for futex `wait(int* addr, int expected)`.
517 /// We pass the base address as the first argument, So this function creates522 /// We pass the base address as the first argument, So this function creates
518 /// an zero-initialized integer with `b` copied at the correct offset.523 /// an zero-initialized integer with `b` copied at the correct offset.
...@@ -525,6 +530,86 @@ private:...@@ -525,6 +530,86 @@ private:
525 static_assert(Wait != nullptr && Wake != nullptr, "");530 static_assert(Wait != nullptr && Wake != nullptr, "");
526};531};
527532
533//===----------------------------------------------------------------------===//
534// GuardObject
535//===----------------------------------------------------------------------===//
536
537enum class AcquireResult {
538 INIT_IS_DONE,
539 INIT_IS_PENDING,
540};
541constexpr AcquireResult INIT_IS_DONE = AcquireResult::INIT_IS_DONE;
542constexpr AcquireResult INIT_IS_PENDING = AcquireResult::INIT_IS_PENDING;
543
544/// Co-ordinates between GuardByte and InitByte.
545template <class InitByteT>
546struct GuardObject {
547 GuardObject() = delete;
548 GuardObject(GuardObject const&) = delete;
549 GuardObject& operator=(GuardObject const&) = delete;
550
551private:
552 GuardByte guard_byte;
553 InitByteT init_byte;
554
555public:
556 /// ARM Constructor
557 explicit GuardObject(uint32_t* raw_guard_object)
558 : guard_byte(reinterpret_cast<uint8_t*>(raw_guard_object)),
559 init_byte(reinterpret_cast<uint8_t*>(raw_guard_object) + 1, nullptr) {}
560
561 /// Itanium Constructor
562 explicit GuardObject(uint64_t* raw_guard_object)
563 : guard_byte(reinterpret_cast<uint8_t*>(raw_guard_object)),
564 init_byte(reinterpret_cast<uint8_t*>(raw_guard_object) + 1, reinterpret_cast<uint32_t*>(raw_guard_object) + 1) {
565 }
566
567 /// Implements __cxa_guard_acquire.
568 AcquireResult cxa_guard_acquire() {
569 // Use short-circuit evaluation to avoid calling init_byte.acquire when
570 // guard_byte.acquire returns true. (i.e. don't call it when we know from
571 // the guard byte that initialization has already been completed)
572 if (guard_byte.acquire() || init_byte.acquire())
573 return INIT_IS_DONE;
574 return INIT_IS_PENDING;
575 }
576
577 /// Implements __cxa_guard_release.
578 void cxa_guard_release() {
579 // Update guard byte first, so if somebody is woken up by init_byte.release
580 // and comes all the way back around to __cxa_guard_acquire again, they see
581 // it as having completed initialization.
582 guard_byte.release();
583 init_byte.release();
584 }
585
586 /// Implements __cxa_guard_abort.
587 void cxa_guard_abort() {
588 guard_byte.abort();
589 init_byte.abort();
590 }
591};
592
593//===----------------------------------------------------------------------===//
594// Convenience Classes
595//===----------------------------------------------------------------------===//
596
597/// NoThreadsGuard - Manages initialization without performing any inter-thread
598/// synchronization.
599using NoThreadsGuard = GuardObject<InitByteNoThreads>;
600
601/// GlobalMutexGuard - Manages initialization using a global mutex and
602/// condition variable.
603template <class Mutex, class CondVar, Mutex& global_mutex, CondVar& global_cond,
604 uint32_t (*GetThreadID)() = PlatformThreadID>
605using GlobalMutexGuard = GuardObject<InitByteGlobalMutex<Mutex, CondVar, global_mutex, global_cond, GetThreadID>>;
606
607/// FutexGuard - Manages initialization using atomics and the futex syscall for
608/// waiting and waking.
609template <void (*Wait)(int*, int) = PlatformFutexWait, void (*Wake)(int*) = PlatformFutexWake,
610 uint32_t (*GetThreadIDArg)() = PlatformThreadID>
611using FutexGuard = GuardObject<InitByteFutex<Wait, Wake, GetThreadIDArg>>;
612
528//===----------------------------------------------------------------------===//613//===----------------------------------------------------------------------===//
529//614//
530//===----------------------------------------------------------------------===//615//===----------------------------------------------------------------------===//
...@@ -536,31 +621,25 @@ struct GlobalStatic {...@@ -536,31 +621,25 @@ struct GlobalStatic {
536template <class T>621template <class T>
537_LIBCPP_SAFE_STATIC T GlobalStatic<T>::instance = {};622_LIBCPP_SAFE_STATIC T GlobalStatic<T>::instance = {};
538623
539enum class Implementation {624enum class Implementation { NoThreads, GlobalMutex, Futex };
540 NoThreads,
541 GlobalLock,
542 Futex
543};
544625
545template <Implementation Impl>626template <Implementation Impl>
546struct SelectImplementation;627struct SelectImplementation;
547628
548template <>629template <>
549struct SelectImplementation<Implementation::NoThreads> {630struct SelectImplementation<Implementation::NoThreads> {
550 using type = InitByteNoThreads;631 using type = NoThreadsGuard;
551};632};
552633
553template <>634template <>
554struct SelectImplementation<Implementation::GlobalLock> {635struct SelectImplementation<Implementation::GlobalMutex> {
555 using type = InitByteGlobalMutex<636 using type = GlobalMutexGuard<LibcppMutex, LibcppCondVar, GlobalStatic<LibcppMutex>::instance,
556 LibcppMutex, LibcppCondVar, GlobalStatic<LibcppMutex>::instance,637 GlobalStatic<LibcppCondVar>::instance, PlatformThreadID>;
557 GlobalStatic<LibcppCondVar>::instance, PlatformThreadID>;
558};638};
559639
560template <>640template <>
561struct SelectImplementation<Implementation::Futex> {641struct SelectImplementation<Implementation::Futex> {
562 using type =642 using type = FutexGuard<PlatformFutexWait, PlatformFutexWake, PlatformThreadID>;
563 InitByteFutex<PlatformFutexWait, PlatformFutexWake, PlatformThreadID>;
564};643};
565644
566// TODO(EricWF): We should prefer the futex implementation when available. But645// TODO(EricWF): We should prefer the futex implementation when available. But
...@@ -571,22 +650,21 @@ constexpr Implementation CurrentImplementation =...@@ -571,22 +650,21 @@ constexpr Implementation CurrentImplementation =
571#elif defined(_LIBCXXABI_USE_FUTEX)650#elif defined(_LIBCXXABI_USE_FUTEX)
572 Implementation::Futex;651 Implementation::Futex;
573#else652#else
574 Implementation::GlobalLock;653 Implementation::GlobalMutex;
575#endif654#endif
576655
577static_assert(CurrentImplementation != Implementation::Futex656static_assert(CurrentImplementation != Implementation::Futex || PlatformSupportsFutex(),
578 || PlatformSupportsFutex(), "Futex selected but not supported");657 "Futex selected but not supported");
579658
580using SelectedImplementation =659using SelectedImplementation = SelectImplementation<CurrentImplementation>::type;
581 SelectImplementation<CurrentImplementation>::type;
582660
583} // end namespace661} // end namespace
584} // end namespace __cxxabiv1662} // end namespace __cxxabiv1
585663
586#if defined(__clang__)664#if defined(__clang__)
587# pragma clang diagnostic pop665# pragma clang diagnostic pop
588#elif defined(__GNUC__)666#elif defined(__GNUC__)
589# pragma GCC diagnostic pop667# pragma GCC diagnostic pop
590#endif668#endif
591669
592#endif // LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H670#endif // LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H
lib/libcxxabi/src/cxa_handlers.cpp+3-13
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------- cxa_handlers.cpp ---------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6//6//
7//7//
8// This file implements the functionality associated with the terminate_handler,8// This file implements the functionality associated with the terminate_handler,
9// unexpected_handler, and new_handler.9// unexpected_handler, and new_handler.
10//===----------------------------------------------------------------------===//10//===----------------------------------------------------------------------===//
1111
12#include <stdexcept>12#include <stdexcept>
...@@ -17,7 +17,7 @@...@@ -17,7 +17,7 @@
17#include "cxa_handlers.h"17#include "cxa_handlers.h"
18#include "cxa_exception.h"18#include "cxa_exception.h"
19#include "private_typeinfo.h"19#include "private_typeinfo.h"
20#include "include/atomic_support.h"20#include "include/atomic_support.h" // from libc++
2121
22namespace std22namespace std
23{23{
...@@ -92,16 +92,6 @@ terminate() noexcept...@@ -92,16 +92,6 @@ terminate() noexcept
92 __terminate(get_terminate());92 __terminate(get_terminate());
93}93}
9494
95extern "C" {
96new_handler __cxa_new_handler = 0;
97}
98
99new_handler
100set_new_handler(new_handler handler) noexcept
101{
102 return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel);
103}
104
105new_handler95new_handler
106get_new_handler() noexcept96get_new_handler() noexcept
107{97{
lib/libcxxabi/src/cxa_handlers.h+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------- cxa_handlers.h -----------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_noexception.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------- cxa_exception.cpp --------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_personality.cpp+16-4
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------- cxa_exception.cpp --------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
...@@ -1004,9 +1004,14 @@ extern "C" _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception*,...@@ -1004,9 +1004,14 @@ extern "C" _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception*,
1004static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception,1004static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception,
1005 _Unwind_Context* context)1005 _Unwind_Context* context)
1006{1006{
1007 if (__gnu_unwind_frame(unwind_exception, context) != _URC_OK)1007 switch (__gnu_unwind_frame(unwind_exception, context)) {
1008 return _URC_FAILURE;1008 case _URC_OK:
1009 return _URC_CONTINUE_UNWIND;1009 return _URC_CONTINUE_UNWIND;
1010 case _URC_END_OF_STACK:
1011 return _URC_END_OF_STACK;
1012 default:
1013 return _URC_FAILURE;
1014 }
1010}1015}
10111016
1012// ARM register names1017// ARM register names
...@@ -1109,7 +1114,14 @@ __gxx_personality_v0(_Unwind_State state,...@@ -1109,7 +1114,14 @@ __gxx_personality_v0(_Unwind_State state,
1109 // Either we didn't do a phase 1 search (due to forced unwinding), or1114 // Either we didn't do a phase 1 search (due to forced unwinding), or
1110 // phase 1 reported no catching-handlers.1115 // phase 1 reported no catching-handlers.
1111 // Search for a (non-catching) cleanup1116 // Search for a (non-catching) cleanup
1112 scan_eh_tab(results, _UA_CLEANUP_PHASE, native_exception, unwind_exception, context);1117 if (is_force_unwinding)
1118 scan_eh_tab(
1119 results,
1120 static_cast<_Unwind_Action>(_UA_CLEANUP_PHASE | _UA_FORCE_UNWIND),
1121 native_exception, unwind_exception, context);
1122 else
1123 scan_eh_tab(results, _UA_CLEANUP_PHASE, native_exception,
1124 unwind_exception, context);
1113 if (results.reason == _URC_HANDLER_FOUND)1125 if (results.reason == _URC_HANDLER_FOUND)
1114 {1126 {
1115 // Found a non-catching handler1127 // Found a non-catching handler
lib/libcxxabi/src/cxa_thread_atexit.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===----------------------- cxa_thread_atexit.cpp ------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_vector.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===-------------------------- cxa_vector.cpp ---------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/cxa_virtual.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===-------------------------- cxa_virtual.cpp ---------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/demangle/ItaniumDemangle.h+740-698
...@@ -6,8 +6,10 @@...@@ -6,8 +6,10 @@
6//6//
7//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
8//8//
9// Generic itanium demangler library. This file has two byte-per-byte identical9// Generic itanium demangler library.
10// copies in the source tree, one in libcxxabi, and the other in llvm.10// There are two copies of this file in the source tree. The one under
11// libcxxabi is the original and the one under llvm is the copy. Use
12// cp-to-llvm.sh to update the copy. See README.txt for more details.
11//13//
12//===----------------------------------------------------------------------===//14//===----------------------------------------------------------------------===//
1315
...@@ -21,12 +23,13 @@...@@ -21,12 +23,13 @@
21#include "DemangleConfig.h"23#include "DemangleConfig.h"
22#include "StringView.h"24#include "StringView.h"
23#include "Utility.h"25#include "Utility.h"
26#include <algorithm>
24#include <cassert>27#include <cassert>
25#include <cctype>28#include <cctype>
26#include <cstdio>29#include <cstdio>
27#include <cstdlib>30#include <cstdlib>
28#include <cstring>31#include <cstring>
29#include <numeric>32#include <limits>
30#include <utility>33#include <utility>
3134
32#define FOR_EACH_NODE_KIND(X) \35#define FOR_EACH_NODE_KIND(X) \
...@@ -57,6 +60,7 @@...@@ -57,6 +60,7 @@
57 X(LocalName) \60 X(LocalName) \
58 X(VectorType) \61 X(VectorType) \
59 X(PixelVectorType) \62 X(PixelVectorType) \
63 X(BinaryFPType) \
60 X(SyntheticTemplateParamName) \64 X(SyntheticTemplateParamName) \
61 X(TypeTemplateParamDecl) \65 X(TypeTemplateParamDecl) \
62 X(NonTypeTemplateParamDecl) \66 X(NonTypeTemplateParamDecl) \
...@@ -109,6 +113,126 @@...@@ -109,6 +113,126 @@
109113
110DEMANGLE_NAMESPACE_BEGIN114DEMANGLE_NAMESPACE_BEGIN
111115
116template <class T, size_t N> class PODSmallVector {
117 static_assert(std::is_pod<T>::value,
118 "T is required to be a plain old data type");
119
120 T *First = nullptr;
121 T *Last = nullptr;
122 T *Cap = nullptr;
123 T Inline[N] = {0};
124
125 bool isInline() const { return First == Inline; }
126
127 void clearInline() {
128 First = Inline;
129 Last = Inline;
130 Cap = Inline + N;
131 }
132
133 void reserve(size_t NewCap) {
134 size_t S = size();
135 if (isInline()) {
136 auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));
137 if (Tmp == nullptr)
138 std::terminate();
139 std::copy(First, Last, Tmp);
140 First = Tmp;
141 } else {
142 First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));
143 if (First == nullptr)
144 std::terminate();
145 }
146 Last = First + S;
147 Cap = First + NewCap;
148 }
149
150public:
151 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
152
153 PODSmallVector(const PODSmallVector &) = delete;
154 PODSmallVector &operator=(const PODSmallVector &) = delete;
155
156 PODSmallVector(PODSmallVector &&Other) : PODSmallVector() {
157 if (Other.isInline()) {
158 std::copy(Other.begin(), Other.end(), First);
159 Last = First + Other.size();
160 Other.clear();
161 return;
162 }
163
164 First = Other.First;
165 Last = Other.Last;
166 Cap = Other.Cap;
167 Other.clearInline();
168 }
169
170 PODSmallVector &operator=(PODSmallVector &&Other) {
171 if (Other.isInline()) {
172 if (!isInline()) {
173 std::free(First);
174 clearInline();
175 }
176 std::copy(Other.begin(), Other.end(), First);
177 Last = First + Other.size();
178 Other.clear();
179 return *this;
180 }
181
182 if (isInline()) {
183 First = Other.First;
184 Last = Other.Last;
185 Cap = Other.Cap;
186 Other.clearInline();
187 return *this;
188 }
189
190 std::swap(First, Other.First);
191 std::swap(Last, Other.Last);
192 std::swap(Cap, Other.Cap);
193 Other.clear();
194 return *this;
195 }
196
197 // NOLINTNEXTLINE(readability-identifier-naming)
198 void push_back(const T &Elem) {
199 if (Last == Cap)
200 reserve(size() * 2);
201 *Last++ = Elem;
202 }
203
204 // NOLINTNEXTLINE(readability-identifier-naming)
205 void pop_back() {
206 assert(Last != First && "Popping empty vector!");
207 --Last;
208 }
209
210 void dropBack(size_t Index) {
211 assert(Index <= size() && "dropBack() can't expand!");
212 Last = First + Index;
213 }
214
215 T *begin() { return First; }
216 T *end() { return Last; }
217
218 bool empty() const { return First == Last; }
219 size_t size() const { return static_cast<size_t>(Last - First); }
220 T &back() {
221 assert(Last != First && "Calling back() on empty vector!");
222 return *(Last - 1);
223 }
224 T &operator[](size_t Index) {
225 assert(Index < size() && "Invalid access!");
226 return *(begin() + Index);
227 }
228 void clear() { Last = First; }
229
230 ~PODSmallVector() {
231 if (!isInline())
232 std::free(First);
233 }
234};
235
112// Base class of all AST nodes. The AST is built by the parser, then is236// Base class of all AST nodes. The AST is built by the parser, then is
113// traversed by the printLeft/Right functions to produce a demangled string.237// traversed by the printLeft/Right functions to produce a demangled string.
114class Node {238class Node {
...@@ -155,50 +279,48 @@ public:...@@ -155,50 +279,48 @@ public:
155 // would construct an equivalent node.279 // would construct an equivalent node.
156 //template<typename Fn> void match(Fn F) const;280 //template<typename Fn> void match(Fn F) const;
157281
158 bool hasRHSComponent(OutputStream &S) const {282 bool hasRHSComponent(OutputBuffer &OB) const {
159 if (RHSComponentCache != Cache::Unknown)283 if (RHSComponentCache != Cache::Unknown)
160 return RHSComponentCache == Cache::Yes;284 return RHSComponentCache == Cache::Yes;
161 return hasRHSComponentSlow(S);285 return hasRHSComponentSlow(OB);
162 }286 }
163287
164 bool hasArray(OutputStream &S) const {288 bool hasArray(OutputBuffer &OB) const {
165 if (ArrayCache != Cache::Unknown)289 if (ArrayCache != Cache::Unknown)
166 return ArrayCache == Cache::Yes;290 return ArrayCache == Cache::Yes;
167 return hasArraySlow(S);291 return hasArraySlow(OB);
168 }292 }
169293
170 bool hasFunction(OutputStream &S) const {294 bool hasFunction(OutputBuffer &OB) const {
171 if (FunctionCache != Cache::Unknown)295 if (FunctionCache != Cache::Unknown)
172 return FunctionCache == Cache::Yes;296 return FunctionCache == Cache::Yes;
173 return hasFunctionSlow(S);297 return hasFunctionSlow(OB);
174 }298 }
175299
176 Kind getKind() const { return K; }300 Kind getKind() const { return K; }
177301
178 virtual bool hasRHSComponentSlow(OutputStream &) const { return false; }302 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }
179 virtual bool hasArraySlow(OutputStream &) const { return false; }303 virtual bool hasArraySlow(OutputBuffer &) const { return false; }
180 virtual bool hasFunctionSlow(OutputStream &) const { return false; }304 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }
181305
182 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to306 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
183 // get at a node that actually represents some concrete syntax.307 // get at a node that actually represents some concrete syntax.
184 virtual const Node *getSyntaxNode(OutputStream &) const {308 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }
185 return this;
186 }
187309
188 void print(OutputStream &S) const {310 void print(OutputBuffer &OB) const {
189 printLeft(S);311 printLeft(OB);
190 if (RHSComponentCache != Cache::No)312 if (RHSComponentCache != Cache::No)
191 printRight(S);313 printRight(OB);
192 }314 }
193315
194 // Print the "left" side of this Node into OutputStream.316 // Print the "left" side of this Node into OutputBuffer.
195 virtual void printLeft(OutputStream &) const = 0;317 virtual void printLeft(OutputBuffer &) const = 0;
196318
197 // Print the "right". This distinction is necessary to represent C++ types319 // Print the "right". This distinction is necessary to represent C++ types
198 // that appear on the RHS of their subtype, such as arrays or functions.320 // that appear on the RHS of their subtype, such as arrays or functions.
199 // Since most types don't have such a component, provide a default321 // Since most types don't have such a component, provide a default
200 // implementation.322 // implementation.
201 virtual void printRight(OutputStream &) const {}323 virtual void printRight(OutputBuffer &) const {}
202324
203 virtual StringView getBaseName() const { return StringView(); }325 virtual StringView getBaseName() const { return StringView(); }
204326
...@@ -227,19 +349,19 @@ public:...@@ -227,19 +349,19 @@ public:
227349
228 Node *operator[](size_t Idx) const { return Elements[Idx]; }350 Node *operator[](size_t Idx) const { return Elements[Idx]; }
229351
230 void printWithComma(OutputStream &S) const {352 void printWithComma(OutputBuffer &OB) const {
231 bool FirstElement = true;353 bool FirstElement = true;
232 for (size_t Idx = 0; Idx != NumElements; ++Idx) {354 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
233 size_t BeforeComma = S.getCurrentPosition();355 size_t BeforeComma = OB.getCurrentPosition();
234 if (!FirstElement)356 if (!FirstElement)
235 S += ", ";357 OB += ", ";
236 size_t AfterComma = S.getCurrentPosition();358 size_t AfterComma = OB.getCurrentPosition();
237 Elements[Idx]->print(S);359 Elements[Idx]->print(OB);
238360
239 // Elements[Idx] is an empty parameter pack expansion, we should erase the361 // Elements[Idx] is an empty parameter pack expansion, we should erase the
240 // comma we just printed.362 // comma we just printed.
241 if (AfterComma == S.getCurrentPosition()) {363 if (AfterComma == OB.getCurrentPosition()) {
242 S.setCurrentPosition(BeforeComma);364 OB.setCurrentPosition(BeforeComma);
243 continue;365 continue;
244 }366 }
245367
...@@ -254,9 +376,7 @@ struct NodeArrayNode : Node {...@@ -254,9 +376,7 @@ struct NodeArrayNode : Node {
254376
255 template<typename Fn> void match(Fn F) const { F(Array); }377 template<typename Fn> void match(Fn F) const { F(Array); }
256378
257 void printLeft(OutputStream &S) const override {379 void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }
258 Array.printWithComma(S);
259 }
260};380};
261381
262class DotSuffix final : public Node {382class DotSuffix final : public Node {
...@@ -269,11 +389,11 @@ public:...@@ -269,11 +389,11 @@ public:
269389
270 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }390 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
271391
272 void printLeft(OutputStream &s) const override {392 void printLeft(OutputBuffer &OB) const override {
273 Prefix->print(s);393 Prefix->print(OB);
274 s += " (";394 OB += " (";
275 s += Suffix;395 OB += Suffix;
276 s += ")";396 OB += ")";
277 }397 }
278};398};
279399
...@@ -288,12 +408,12 @@ public:...@@ -288,12 +408,12 @@ public:
288408
289 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }409 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
290410
291 void printLeft(OutputStream &S) const override {411 void printLeft(OutputBuffer &OB) const override {
292 Ty->print(S);412 Ty->print(OB);
293 S += " ";413 OB += " ";
294 S += Ext;414 OB += Ext;
295 if (TA != nullptr)415 if (TA != nullptr)
296 TA->print(S);416 TA->print(OB);
297 }417 }
298};418};
299419
...@@ -319,13 +439,13 @@ protected:...@@ -319,13 +439,13 @@ protected:
319 const Qualifiers Quals;439 const Qualifiers Quals;
320 const Node *Child;440 const Node *Child;
321441
322 void printQuals(OutputStream &S) const {442 void printQuals(OutputBuffer &OB) const {
323 if (Quals & QualConst)443 if (Quals & QualConst)
324 S += " const";444 OB += " const";
325 if (Quals & QualVolatile)445 if (Quals & QualVolatile)
326 S += " volatile";446 OB += " volatile";
327 if (Quals & QualRestrict)447 if (Quals & QualRestrict)
328 S += " restrict";448 OB += " restrict";
329 }449 }
330450
331public:451public:
...@@ -336,22 +456,22 @@ public:...@@ -336,22 +456,22 @@ public:
336456
337 template<typename Fn> void match(Fn F) const { F(Child, Quals); }457 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
338458
339 bool hasRHSComponentSlow(OutputStream &S) const override {459 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
340 return Child->hasRHSComponent(S);460 return Child->hasRHSComponent(OB);
341 }461 }
342 bool hasArraySlow(OutputStream &S) const override {462 bool hasArraySlow(OutputBuffer &OB) const override {
343 return Child->hasArray(S);463 return Child->hasArray(OB);
344 }464 }
345 bool hasFunctionSlow(OutputStream &S) const override {465 bool hasFunctionSlow(OutputBuffer &OB) const override {
346 return Child->hasFunction(S);466 return Child->hasFunction(OB);
347 }467 }
348468
349 void printLeft(OutputStream &S) const override {469 void printLeft(OutputBuffer &OB) const override {
350 Child->printLeft(S);470 Child->printLeft(OB);
351 printQuals(S);471 printQuals(OB);
352 }472 }
353473
354 void printRight(OutputStream &S) const override { Child->printRight(S); }474 void printRight(OutputBuffer &OB) const override { Child->printRight(OB); }
355};475};
356476
357class ConversionOperatorType final : public Node {477class ConversionOperatorType final : public Node {
...@@ -363,9 +483,9 @@ public:...@@ -363,9 +483,9 @@ public:
363483
364 template<typename Fn> void match(Fn F) const { F(Ty); }484 template<typename Fn> void match(Fn F) const { F(Ty); }
365485
366 void printLeft(OutputStream &S) const override {486 void printLeft(OutputBuffer &OB) const override {
367 S += "operator ";487 OB += "operator ";
368 Ty->print(S);488 Ty->print(OB);
369 }489 }
370};490};
371491
...@@ -379,9 +499,9 @@ public:...@@ -379,9 +499,9 @@ public:
379499
380 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }500 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
381501
382 void printLeft(OutputStream &s) const override {502 void printLeft(OutputBuffer &OB) const override {
383 Ty->printLeft(s);503 Ty->printLeft(OB);
384 s += Postfix;504 OB += Postfix;
385 }505 }
386};506};
387507
...@@ -396,7 +516,7 @@ public:...@@ -396,7 +516,7 @@ public:
396 StringView getName() const { return Name; }516 StringView getName() const { return Name; }
397 StringView getBaseName() const override { return Name; }517 StringView getBaseName() const override { return Name; }
398518
399 void printLeft(OutputStream &s) const override { s += Name; }519 void printLeft(OutputBuffer &OB) const override { OB += Name; }
400};520};
401521
402class ElaboratedTypeSpefType : public Node {522class ElaboratedTypeSpefType : public Node {
...@@ -408,10 +528,10 @@ public:...@@ -408,10 +528,10 @@ public:
408528
409 template<typename Fn> void match(Fn F) const { F(Kind, Child); }529 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
410530
411 void printLeft(OutputStream &S) const override {531 void printLeft(OutputBuffer &OB) const override {
412 S += Kind;532 OB += Kind;
413 S += ' ';533 OB += ' ';
414 Child->print(S);534 Child->print(OB);
415 }535 }
416};536};
417537
...@@ -426,11 +546,11 @@ struct AbiTagAttr : Node {...@@ -426,11 +546,11 @@ struct AbiTagAttr : Node {
426546
427 template<typename Fn> void match(Fn F) const { F(Base, Tag); }547 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
428548
429 void printLeft(OutputStream &S) const override {549 void printLeft(OutputBuffer &OB) const override {
430 Base->printLeft(S);550 Base->printLeft(OB);
431 S += "[abi:";551 OB += "[abi:";
432 S += Tag;552 OB += Tag;
433 S += "]";553 OB += "]";
434 }554 }
435};555};
436556
...@@ -442,10 +562,10 @@ public:...@@ -442,10 +562,10 @@ public:
442562
443 template<typename Fn> void match(Fn F) const { F(Conditions); }563 template<typename Fn> void match(Fn F) const { F(Conditions); }
444564
445 void printLeft(OutputStream &S) const override {565 void printLeft(OutputBuffer &OB) const override {
446 S += " [enable_if:";566 OB += " [enable_if:";
447 Conditions.printWithComma(S);567 Conditions.printWithComma(OB);
448 S += ']';568 OB += ']';
449 }569 }
450};570};
451571
...@@ -466,11 +586,11 @@ public:...@@ -466,11 +586,11 @@ public:
466 static_cast<const NameType *>(Ty)->getName() == "objc_object";586 static_cast<const NameType *>(Ty)->getName() == "objc_object";
467 }587 }
468588
469 void printLeft(OutputStream &S) const override {589 void printLeft(OutputBuffer &OB) const override {
470 Ty->print(S);590 Ty->print(OB);
471 S += "<";591 OB += "<";
472 S += Protocol;592 OB += Protocol;
473 S += ">";593 OB += ">";
474 }594 }
475};595};
476596
...@@ -484,34 +604,34 @@ public:...@@ -484,34 +604,34 @@ public:
484604
485 template<typename Fn> void match(Fn F) const { F(Pointee); }605 template<typename Fn> void match(Fn F) const { F(Pointee); }
486606
487 bool hasRHSComponentSlow(OutputStream &S) const override {607 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
488 return Pointee->hasRHSComponent(S);608 return Pointee->hasRHSComponent(OB);
489 }609 }
490610
491 void printLeft(OutputStream &s) const override {611 void printLeft(OutputBuffer &OB) const override {
492 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.612 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
493 if (Pointee->getKind() != KObjCProtoName ||613 if (Pointee->getKind() != KObjCProtoName ||
494 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {614 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
495 Pointee->printLeft(s);615 Pointee->printLeft(OB);
496 if (Pointee->hasArray(s))616 if (Pointee->hasArray(OB))
497 s += " ";617 OB += " ";
498 if (Pointee->hasArray(s) || Pointee->hasFunction(s))618 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
499 s += "(";619 OB += "(";
500 s += "*";620 OB += "*";
501 } else {621 } else {
502 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);622 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
503 s += "id<";623 OB += "id<";
504 s += objcProto->Protocol;624 OB += objcProto->Protocol;
505 s += ">";625 OB += ">";
506 }626 }
507 }627 }
508628
509 void printRight(OutputStream &s) const override {629 void printRight(OutputBuffer &OB) const override {
510 if (Pointee->getKind() != KObjCProtoName ||630 if (Pointee->getKind() != KObjCProtoName ||
511 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {631 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
512 if (Pointee->hasArray(s) || Pointee->hasFunction(s))632 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
513 s += ")";633 OB += ")";
514 Pointee->printRight(s);634 Pointee->printRight(OB);
515 }635 }
516 }636 }
517};637};
...@@ -531,15 +651,30 @@ class ReferenceType : public Node {...@@ -531,15 +651,30 @@ class ReferenceType : public Node {
531 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The651 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
532 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any652 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
533 // other combination collapses to a lvalue ref.653 // other combination collapses to a lvalue ref.
534 std::pair<ReferenceKind, const Node *> collapse(OutputStream &S) const {654 //
655 // A combination of a TemplateForwardReference and a back-ref Substitution
656 // from an ill-formed string may have created a cycle; use cycle detection to
657 // avoid looping forever.
658 std::pair<ReferenceKind, const Node *> collapse(OutputBuffer &OB) const {
535 auto SoFar = std::make_pair(RK, Pointee);659 auto SoFar = std::make_pair(RK, Pointee);
660 // Track the chain of nodes for the Floyd's 'tortoise and hare'
661 // cycle-detection algorithm, since getSyntaxNode(S) is impure
662 PODSmallVector<const Node *, 8> Prev;
536 for (;;) {663 for (;;) {
537 const Node *SN = SoFar.second->getSyntaxNode(S);664 const Node *SN = SoFar.second->getSyntaxNode(OB);
538 if (SN->getKind() != KReferenceType)665 if (SN->getKind() != KReferenceType)
539 break;666 break;
540 auto *RT = static_cast<const ReferenceType *>(SN);667 auto *RT = static_cast<const ReferenceType *>(SN);
541 SoFar.second = RT->Pointee;668 SoFar.second = RT->Pointee;
542 SoFar.first = std::min(SoFar.first, RT->RK);669 SoFar.first = std::min(SoFar.first, RT->RK);
670
671 // The middle of Prev is the 'slow' pointer moving at half speed
672 Prev.push_back(SoFar.second);
673 if (Prev.size() > 1 && SoFar.second == Prev[(Prev.size() - 1) / 2]) {
674 // Cycle detected
675 SoFar.second = nullptr;
676 break;
677 }
543 }678 }
544 return SoFar;679 return SoFar;
545 }680 }
...@@ -551,31 +686,35 @@ public:...@@ -551,31 +686,35 @@ public:
551686
552 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }687 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
553688
554 bool hasRHSComponentSlow(OutputStream &S) const override {689 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
555 return Pointee->hasRHSComponent(S);690 return Pointee->hasRHSComponent(OB);
556 }691 }
557692
558 void printLeft(OutputStream &s) const override {693 void printLeft(OutputBuffer &OB) const override {
559 if (Printing)694 if (Printing)
560 return;695 return;
561 SwapAndRestore<bool> SavePrinting(Printing, true);696 SwapAndRestore<bool> SavePrinting(Printing, true);
562 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);697 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
563 Collapsed.second->printLeft(s);698 if (!Collapsed.second)
564 if (Collapsed.second->hasArray(s))699 return;
565 s += " ";700 Collapsed.second->printLeft(OB);
566 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))701 if (Collapsed.second->hasArray(OB))
567 s += "(";702 OB += " ";
703 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
704 OB += "(";
568705
569 s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");706 OB += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
570 }707 }
571 void printRight(OutputStream &s) const override {708 void printRight(OutputBuffer &OB) const override {
572 if (Printing)709 if (Printing)
573 return;710 return;
574 SwapAndRestore<bool> SavePrinting(Printing, true);711 SwapAndRestore<bool> SavePrinting(Printing, true);
575 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);712 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
576 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))713 if (!Collapsed.second)
577 s += ")";714 return;
578 Collapsed.second->printRight(s);715 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
716 OB += ")";
717 Collapsed.second->printRight(OB);
579 }718 }
580};719};
581720
...@@ -590,24 +729,24 @@ public:...@@ -590,24 +729,24 @@ public:
590729
591 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }730 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
592731
593 bool hasRHSComponentSlow(OutputStream &S) const override {732 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
594 return MemberType->hasRHSComponent(S);733 return MemberType->hasRHSComponent(OB);
595 }734 }
596735
597 void printLeft(OutputStream &s) const override {736 void printLeft(OutputBuffer &OB) const override {
598 MemberType->printLeft(s);737 MemberType->printLeft(OB);
599 if (MemberType->hasArray(s) || MemberType->hasFunction(s))738 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
600 s += "(";739 OB += "(";
601 else740 else
602 s += " ";741 OB += " ";
603 ClassType->print(s);742 ClassType->print(OB);
604 s += "::*";743 OB += "::*";
605 }744 }
606745
607 void printRight(OutputStream &s) const override {746 void printRight(OutputBuffer &OB) const override {
608 if (MemberType->hasArray(s) || MemberType->hasFunction(s))747 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
609 s += ")";748 OB += ")";
610 MemberType->printRight(s);749 MemberType->printRight(OB);
611 }750 }
612};751};
613752
...@@ -624,19 +763,19 @@ public:...@@ -624,19 +763,19 @@ public:
624763
625 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }764 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
626765
627 bool hasRHSComponentSlow(OutputStream &) const override { return true; }766 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
628 bool hasArraySlow(OutputStream &) const override { return true; }767 bool hasArraySlow(OutputBuffer &) const override { return true; }
629768
630 void printLeft(OutputStream &S) const override { Base->printLeft(S); }769 void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); }
631770
632 void printRight(OutputStream &S) const override {771 void printRight(OutputBuffer &OB) const override {
633 if (S.back() != ']')772 if (OB.back() != ']')
634 S += " ";773 OB += " ";
635 S += "[";774 OB += "[";
636 if (Dimension)775 if (Dimension)
637 Dimension->print(S);776 Dimension->print(OB);
638 S += "]";777 OB += "]";
639 Base->printRight(S);778 Base->printRight(OB);
640 }779 }
641};780};
642781
...@@ -660,8 +799,8 @@ public:...@@ -660,8 +799,8 @@ public:
660 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);799 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
661 }800 }
662801
663 bool hasRHSComponentSlow(OutputStream &) const override { return true; }802 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
664 bool hasFunctionSlow(OutputStream &) const override { return true; }803 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
665804
666 // Handle C++'s ... quirky decl grammar by using the left & right805 // Handle C++'s ... quirky decl grammar by using the left & right
667 // distinction. Consider:806 // distinction. Consider:
...@@ -670,32 +809,32 @@ public:...@@ -670,32 +809,32 @@ public:
670 // that takes a char and returns an int. If we're trying to print f, start809 // that takes a char and returns an int. If we're trying to print f, start
671 // by printing out the return types's left, then print our parameters, then810 // by printing out the return types's left, then print our parameters, then
672 // finally print right of the return type.811 // finally print right of the return type.
673 void printLeft(OutputStream &S) const override {812 void printLeft(OutputBuffer &OB) const override {
674 Ret->printLeft(S);813 Ret->printLeft(OB);
675 S += " ";814 OB += " ";
676 }815 }
677816
678 void printRight(OutputStream &S) const override {817 void printRight(OutputBuffer &OB) const override {
679 S += "(";818 OB += "(";
680 Params.printWithComma(S);819 Params.printWithComma(OB);
681 S += ")";820 OB += ")";
682 Ret->printRight(S);821 Ret->printRight(OB);
683822
684 if (CVQuals & QualConst)823 if (CVQuals & QualConst)
685 S += " const";824 OB += " const";
686 if (CVQuals & QualVolatile)825 if (CVQuals & QualVolatile)
687 S += " volatile";826 OB += " volatile";
688 if (CVQuals & QualRestrict)827 if (CVQuals & QualRestrict)
689 S += " restrict";828 OB += " restrict";
690829
691 if (RefQual == FrefQualLValue)830 if (RefQual == FrefQualLValue)
692 S += " &";831 OB += " &";
693 else if (RefQual == FrefQualRValue)832 else if (RefQual == FrefQualRValue)
694 S += " &&";833 OB += " &&";
695834
696 if (ExceptionSpec != nullptr) {835 if (ExceptionSpec != nullptr) {
697 S += ' ';836 OB += ' ';
698 ExceptionSpec->print(S);837 ExceptionSpec->print(OB);
699 }838 }
700 }839 }
701};840};
...@@ -707,10 +846,10 @@ public:...@@ -707,10 +846,10 @@ public:
707846
708 template<typename Fn> void match(Fn F) const { F(E); }847 template<typename Fn> void match(Fn F) const { F(E); }
709848
710 void printLeft(OutputStream &S) const override {849 void printLeft(OutputBuffer &OB) const override {
711 S += "noexcept(";850 OB += "noexcept(";
712 E->print(S);851 E->print(OB);
713 S += ")";852 OB += ")";
714 }853 }
715};854};
716855
...@@ -722,10 +861,10 @@ public:...@@ -722,10 +861,10 @@ public:
722861
723 template<typename Fn> void match(Fn F) const { F(Types); }862 template<typename Fn> void match(Fn F) const { F(Types); }
724863
725 void printLeft(OutputStream &S) const override {864 void printLeft(OutputBuffer &OB) const override {
726 S += "throw(";865 OB += "throw(";
727 Types.printWithComma(S);866 Types.printWithComma(OB);
728 S += ')';867 OB += ')';
729 }868 }
730};869};
731870
...@@ -756,41 +895,41 @@ public:...@@ -756,41 +895,41 @@ public:
756 NodeArray getParams() const { return Params; }895 NodeArray getParams() const { return Params; }
757 const Node *getReturnType() const { return Ret; }896 const Node *getReturnType() const { return Ret; }
758897
759 bool hasRHSComponentSlow(OutputStream &) const override { return true; }898 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
760 bool hasFunctionSlow(OutputStream &) const override { return true; }899 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
761900
762 const Node *getName() const { return Name; }901 const Node *getName() const { return Name; }
763902
764 void printLeft(OutputStream &S) const override {903 void printLeft(OutputBuffer &OB) const override {
765 if (Ret) {904 if (Ret) {
766 Ret->printLeft(S);905 Ret->printLeft(OB);
767 if (!Ret->hasRHSComponent(S))906 if (!Ret->hasRHSComponent(OB))
768 S += " ";907 OB += " ";
769 }908 }
770 Name->print(S);909 Name->print(OB);
771 }910 }
772911
773 void printRight(OutputStream &S) const override {912 void printRight(OutputBuffer &OB) const override {
774 S += "(";913 OB += "(";
775 Params.printWithComma(S);914 Params.printWithComma(OB);
776 S += ")";915 OB += ")";
777 if (Ret)916 if (Ret)
778 Ret->printRight(S);917 Ret->printRight(OB);
779918
780 if (CVQuals & QualConst)919 if (CVQuals & QualConst)
781 S += " const";920 OB += " const";
782 if (CVQuals & QualVolatile)921 if (CVQuals & QualVolatile)
783 S += " volatile";922 OB += " volatile";
784 if (CVQuals & QualRestrict)923 if (CVQuals & QualRestrict)
785 S += " restrict";924 OB += " restrict";
786925
787 if (RefQual == FrefQualLValue)926 if (RefQual == FrefQualLValue)
788 S += " &";927 OB += " &";
789 else if (RefQual == FrefQualRValue)928 else if (RefQual == FrefQualRValue)
790 S += " &&";929 OB += " &&";
791930
792 if (Attrs != nullptr)931 if (Attrs != nullptr)
793 Attrs->print(S);932 Attrs->print(OB);
794 }933 }
795};934};
796935
...@@ -803,9 +942,9 @@ public:...@@ -803,9 +942,9 @@ public:
803942
804 template<typename Fn> void match(Fn F) const { F(OpName); }943 template<typename Fn> void match(Fn F) const { F(OpName); }
805944
806 void printLeft(OutputStream &S) const override {945 void printLeft(OutputBuffer &OB) const override {
807 S += "operator\"\" ";946 OB += "operator\"\" ";
808 OpName->print(S);947 OpName->print(OB);
809 }948 }
810};949};
811950
...@@ -819,9 +958,9 @@ public:...@@ -819,9 +958,9 @@ public:
819958
820 template<typename Fn> void match(Fn F) const { F(Special, Child); }959 template<typename Fn> void match(Fn F) const { F(Special, Child); }
821960
822 void printLeft(OutputStream &S) const override {961 void printLeft(OutputBuffer &OB) const override {
823 S += Special;962 OB += Special;
824 Child->print(S);963 Child->print(OB);
825 }964 }
826};965};
827966
...@@ -836,11 +975,11 @@ public:...@@ -836,11 +975,11 @@ public:
836975
837 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }976 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
838977
839 void printLeft(OutputStream &S) const override {978 void printLeft(OutputBuffer &OB) const override {
840 S += "construction vtable for ";979 OB += "construction vtable for ";
841 FirstType->print(S);980 FirstType->print(OB);
842 S += "-in-";981 OB += "-in-";
843 SecondType->print(S);982 SecondType->print(OB);
844 }983 }
845};984};
846985
...@@ -855,10 +994,10 @@ struct NestedName : Node {...@@ -855,10 +994,10 @@ struct NestedName : Node {
855994
856 StringView getBaseName() const override { return Name->getBaseName(); }995 StringView getBaseName() const override { return Name->getBaseName(); }
857996
858 void printLeft(OutputStream &S) const override {997 void printLeft(OutputBuffer &OB) const override {
859 Qual->print(S);998 Qual->print(OB);
860 S += "::";999 OB += "::";
861 Name->print(S);1000 Name->print(OB);
862 }1001 }
863};1002};
8641003
...@@ -871,10 +1010,10 @@ struct LocalName : Node {...@@ -871,10 +1010,10 @@ struct LocalName : Node {
8711010
872 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }1011 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
8731012
874 void printLeft(OutputStream &S) const override {1013 void printLeft(OutputBuffer &OB) const override {
875 Encoding->print(S);1014 Encoding->print(OB);
876 S += "::";1015 OB += "::";
877 Entity->print(S);1016 Entity->print(OB);
878 }1017 }
879};1018};
8801019
...@@ -891,10 +1030,10 @@ public:...@@ -891,10 +1030,10 @@ public:
8911030
892 StringView getBaseName() const override { return Name->getBaseName(); }1031 StringView getBaseName() const override { return Name->getBaseName(); }
8931032
894 void printLeft(OutputStream &S) const override {1033 void printLeft(OutputBuffer &OB) const override {
895 Qualifier->print(S);1034 Qualifier->print(OB);
896 S += "::";1035 OB += "::";
897 Name->print(S);1036 Name->print(OB);
898 }1037 }
899};1038};
9001039
...@@ -909,12 +1048,12 @@ public:...@@ -909,12 +1048,12 @@ public:
9091048
910 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }1049 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
9111050
912 void printLeft(OutputStream &S) const override {1051 void printLeft(OutputBuffer &OB) const override {
913 BaseType->print(S);1052 BaseType->print(OB);
914 S += " vector[";1053 OB += " vector[";
915 if (Dimension)1054 if (Dimension)
916 Dimension->print(S);1055 Dimension->print(OB);
917 S += "]";1056 OB += "]";
918 }1057 }
919};1058};
9201059
...@@ -927,11 +1066,26 @@ public:...@@ -927,11 +1066,26 @@ public:
9271066
928 template<typename Fn> void match(Fn F) const { F(Dimension); }1067 template<typename Fn> void match(Fn F) const { F(Dimension); }
9291068
930 void printLeft(OutputStream &S) const override {1069 void printLeft(OutputBuffer &OB) const override {
931 // FIXME: This should demangle as "vector pixel".1070 // FIXME: This should demangle as "vector pixel".
932 S += "pixel vector[";1071 OB += "pixel vector[";
933 Dimension->print(S);1072 Dimension->print(OB);
934 S += "]";1073 OB += "]";
1074 }
1075};
1076
1077class BinaryFPType final : public Node {
1078 const Node *Dimension;
1079
1080public:
1081 BinaryFPType(const Node *Dimension_)
1082 : Node(KBinaryFPType), Dimension(Dimension_) {}
1083
1084 template<typename Fn> void match(Fn F) const { F(Dimension); }
1085
1086 void printLeft(OutputBuffer &OB) const override {
1087 OB += "_Float";
1088 Dimension->print(OB);
935 }1089 }
936};1090};
9371091
...@@ -953,20 +1107,20 @@ public:...@@ -953,20 +1107,20 @@ public:
9531107
954 template<typename Fn> void match(Fn F) const { F(Kind, Index); }1108 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
9551109
956 void printLeft(OutputStream &S) const override {1110 void printLeft(OutputBuffer &OB) const override {
957 switch (Kind) {1111 switch (Kind) {
958 case TemplateParamKind::Type:1112 case TemplateParamKind::Type:
959 S += "$T";1113 OB += "$T";
960 break;1114 break;
961 case TemplateParamKind::NonType:1115 case TemplateParamKind::NonType:
962 S += "$N";1116 OB += "$N";
963 break;1117 break;
964 case TemplateParamKind::Template:1118 case TemplateParamKind::Template:
965 S += "$TT";1119 OB += "$TT";
966 break;1120 break;
967 }1121 }
968 if (Index > 0)1122 if (Index > 0)
969 S << Index - 1;1123 OB << Index - 1;
970 }1124 }
971};1125};
9721126
...@@ -980,13 +1134,9 @@ public:...@@ -980,13 +1134,9 @@ public:
9801134
981 template<typename Fn> void match(Fn F) const { F(Name); }1135 template<typename Fn> void match(Fn F) const { F(Name); }
9821136
983 void printLeft(OutputStream &S) const override {1137 void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
984 S += "typename ";
985 }
9861138
987 void printRight(OutputStream &S) const override {1139 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
988 Name->print(S);
989 }
990};1140};
9911141
992/// A non-type template parameter declaration, 'int N'.1142/// A non-type template parameter declaration, 'int N'.
...@@ -1000,15 +1150,15 @@ public:...@@ -1000,15 +1150,15 @@ public:
10001150
1001 template<typename Fn> void match(Fn F) const { F(Name, Type); }1151 template<typename Fn> void match(Fn F) const { F(Name, Type); }
10021152
1003 void printLeft(OutputStream &S) const override {1153 void printLeft(OutputBuffer &OB) const override {
1004 Type->printLeft(S);1154 Type->printLeft(OB);
1005 if (!Type->hasRHSComponent(S))1155 if (!Type->hasRHSComponent(OB))
1006 S += " ";1156 OB += " ";
1007 }1157 }
10081158
1009 void printRight(OutputStream &S) const override {1159 void printRight(OutputBuffer &OB) const override {
1010 Name->print(S);1160 Name->print(OB);
1011 Type->printRight(S);1161 Type->printRight(OB);
1012 }1162 }
1013};1163};
10141164
...@@ -1025,15 +1175,13 @@ public:...@@ -1025,15 +1175,13 @@ public:
10251175
1026 template<typename Fn> void match(Fn F) const { F(Name, Params); }1176 template<typename Fn> void match(Fn F) const { F(Name, Params); }
10271177
1028 void printLeft(OutputStream &S) const override {1178 void printLeft(OutputBuffer &OB) const override {
1029 S += "template<";1179 OB += "template<";
1030 Params.printWithComma(S);1180 Params.printWithComma(OB);
1031 S += "> typename ";1181 OB += "> typename ";
1032 }1182 }
10331183
1034 void printRight(OutputStream &S) const override {1184 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
1035 Name->print(S);
1036 }
1037};1185};
10381186
1039/// A template parameter pack declaration, 'typename ...T'.1187/// A template parameter pack declaration, 'typename ...T'.
...@@ -1046,14 +1194,12 @@ public:...@@ -1046,14 +1194,12 @@ public:
10461194
1047 template<typename Fn> void match(Fn F) const { F(Param); }1195 template<typename Fn> void match(Fn F) const { F(Param); }
10481196
1049 void printLeft(OutputStream &S) const override {1197 void printLeft(OutputBuffer &OB) const override {
1050 Param->printLeft(S);1198 Param->printLeft(OB);
1051 S += "...";1199 OB += "...";
1052 }1200 }
10531201
1054 void printRight(OutputStream &S) const override {1202 void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
1055 Param->printRight(S);
1056 }
1057};1203};
10581204
1059/// An unexpanded parameter pack (either in the expression or type context). If1205/// An unexpanded parameter pack (either in the expression or type context). If
...@@ -1067,11 +1213,12 @@ public:...@@ -1067,11 +1213,12 @@ public:
1067class ParameterPack final : public Node {1213class ParameterPack final : public Node {
1068 NodeArray Data;1214 NodeArray Data;
10691215
1070 // Setup OutputStream for a pack expansion unless we're already expanding one.1216 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1071 void initializePackExpansion(OutputStream &S) const {1217 // one.
1072 if (S.CurrentPackMax == std::numeric_limits<unsigned>::max()) {1218 void initializePackExpansion(OutputBuffer &OB) const {
1073 S.CurrentPackMax = static_cast<unsigned>(Data.size());1219 if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1074 S.CurrentPackIndex = 0;1220 OB.CurrentPackMax = static_cast<unsigned>(Data.size());
1221 OB.CurrentPackIndex = 0;
1075 }1222 }
1076 }1223 }
10771224
...@@ -1094,38 +1241,38 @@ public:...@@ -1094,38 +1241,38 @@ public:
10941241
1095 template<typename Fn> void match(Fn F) const { F(Data); }1242 template<typename Fn> void match(Fn F) const { F(Data); }
10961243
1097 bool hasRHSComponentSlow(OutputStream &S) const override {1244 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1098 initializePackExpansion(S);1245 initializePackExpansion(OB);
1099 size_t Idx = S.CurrentPackIndex;1246 size_t Idx = OB.CurrentPackIndex;
1100 return Idx < Data.size() && Data[Idx]->hasRHSComponent(S);1247 return Idx < Data.size() && Data[Idx]->hasRHSComponent(OB);
1101 }1248 }
1102 bool hasArraySlow(OutputStream &S) const override {1249 bool hasArraySlow(OutputBuffer &OB) const override {
1103 initializePackExpansion(S);1250 initializePackExpansion(OB);
1104 size_t Idx = S.CurrentPackIndex;1251 size_t Idx = OB.CurrentPackIndex;
1105 return Idx < Data.size() && Data[Idx]->hasArray(S);1252 return Idx < Data.size() && Data[Idx]->hasArray(OB);
1106 }1253 }
1107 bool hasFunctionSlow(OutputStream &S) const override {1254 bool hasFunctionSlow(OutputBuffer &OB) const override {
1108 initializePackExpansion(S);1255 initializePackExpansion(OB);
1109 size_t Idx = S.CurrentPackIndex;1256 size_t Idx = OB.CurrentPackIndex;
1110 return Idx < Data.size() && Data[Idx]->hasFunction(S);1257 return Idx < Data.size() && Data[Idx]->hasFunction(OB);
1111 }1258 }
1112 const Node *getSyntaxNode(OutputStream &S) const override {1259 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1113 initializePackExpansion(S);1260 initializePackExpansion(OB);
1114 size_t Idx = S.CurrentPackIndex;1261 size_t Idx = OB.CurrentPackIndex;
1115 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this;1262 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this;
1116 }1263 }
11171264
1118 void printLeft(OutputStream &S) const override {1265 void printLeft(OutputBuffer &OB) const override {
1119 initializePackExpansion(S);1266 initializePackExpansion(OB);
1120 size_t Idx = S.CurrentPackIndex;1267 size_t Idx = OB.CurrentPackIndex;
1121 if (Idx < Data.size())1268 if (Idx < Data.size())
1122 Data[Idx]->printLeft(S);1269 Data[Idx]->printLeft(OB);
1123 }1270 }
1124 void printRight(OutputStream &S) const override {1271 void printRight(OutputBuffer &OB) const override {
1125 initializePackExpansion(S);1272 initializePackExpansion(OB);
1126 size_t Idx = S.CurrentPackIndex;1273 size_t Idx = OB.CurrentPackIndex;
1127 if (Idx < Data.size())1274 if (Idx < Data.size())
1128 Data[Idx]->printRight(S);1275 Data[Idx]->printRight(OB);
1129 }1276 }
1130};1277};
11311278
...@@ -1144,8 +1291,8 @@ public:...@@ -1144,8 +1291,8 @@ public:
11441291
1145 NodeArray getElements() const { return Elements; }1292 NodeArray getElements() const { return Elements; }
11461293
1147 void printLeft(OutputStream &S) const override {1294 void printLeft(OutputBuffer &OB) const override {
1148 Elements.printWithComma(S);1295 Elements.printWithComma(OB);
1149 }1296 }
1150};1297};
11511298
...@@ -1162,35 +1309,35 @@ public:...@@ -1162,35 +1309,35 @@ public:
11621309
1163 const Node *getChild() const { return Child; }1310 const Node *getChild() const { return Child; }
11641311
1165 void printLeft(OutputStream &S) const override {1312 void printLeft(OutputBuffer &OB) const override {
1166 constexpr unsigned Max = std::numeric_limits<unsigned>::max();1313 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
1167 SwapAndRestore<unsigned> SavePackIdx(S.CurrentPackIndex, Max);1314 SwapAndRestore<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1168 SwapAndRestore<unsigned> SavePackMax(S.CurrentPackMax, Max);1315 SwapAndRestore<unsigned> SavePackMax(OB.CurrentPackMax, Max);
1169 size_t StreamPos = S.getCurrentPosition();1316 size_t StreamPos = OB.getCurrentPosition();
11701317
1171 // Print the first element in the pack. If Child contains a ParameterPack,1318 // Print the first element in the pack. If Child contains a ParameterPack,
1172 // it will set up S.CurrentPackMax and print the first element.1319 // it will set up S.CurrentPackMax and print the first element.
1173 Child->print(S);1320 Child->print(OB);
11741321
1175 // No ParameterPack was found in Child. This can occur if we've found a pack1322 // No ParameterPack was found in Child. This can occur if we've found a pack
1176 // expansion on a <function-param>.1323 // expansion on a <function-param>.
1177 if (S.CurrentPackMax == Max) {1324 if (OB.CurrentPackMax == Max) {
1178 S += "...";1325 OB += "...";
1179 return;1326 return;
1180 }1327 }
11811328
1182 // We found a ParameterPack, but it has no elements. Erase whatever we may1329 // We found a ParameterPack, but it has no elements. Erase whatever we may
1183 // of printed.1330 // of printed.
1184 if (S.CurrentPackMax == 0) {1331 if (OB.CurrentPackMax == 0) {
1185 S.setCurrentPosition(StreamPos);1332 OB.setCurrentPosition(StreamPos);
1186 return;1333 return;
1187 }1334 }
11881335
1189 // Else, iterate through the rest of the elements in the pack.1336 // Else, iterate through the rest of the elements in the pack.
1190 for (unsigned I = 1, E = S.CurrentPackMax; I < E; ++I) {1337 for (unsigned I = 1, E = OB.CurrentPackMax; I < E; ++I) {
1191 S += ", ";1338 OB += ", ";
1192 S.CurrentPackIndex = I;1339 OB.CurrentPackIndex = I;
1193 Child->print(S);1340 Child->print(OB);
1194 }1341 }
1195 }1342 }
1196};1343};
...@@ -1205,12 +1352,12 @@ public:...@@ -1205,12 +1352,12 @@ public:
12051352
1206 NodeArray getParams() { return Params; }1353 NodeArray getParams() { return Params; }
12071354
1208 void printLeft(OutputStream &S) const override {1355 void printLeft(OutputBuffer &OB) const override {
1209 S += "<";1356 OB += "<";
1210 Params.printWithComma(S);1357 Params.printWithComma(OB);
1211 if (S.back() == '>')1358 if (OB.back() == '>')
1212 S += " ";1359 OB += " ";
1213 S += ">";1360 OB += ">";
1214 }1361 }
1215};1362};
12161363
...@@ -1252,42 +1399,42 @@ struct ForwardTemplateReference : Node {...@@ -1252,42 +1399,42 @@ struct ForwardTemplateReference : Node {
1252 // special handling.1399 // special handling.
1253 template<typename Fn> void match(Fn F) const = delete;1400 template<typename Fn> void match(Fn F) const = delete;
12541401
1255 bool hasRHSComponentSlow(OutputStream &S) const override {1402 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1256 if (Printing)1403 if (Printing)
1257 return false;1404 return false;
1258 SwapAndRestore<bool> SavePrinting(Printing, true);1405 SwapAndRestore<bool> SavePrinting(Printing, true);
1259 return Ref->hasRHSComponent(S);1406 return Ref->hasRHSComponent(OB);
1260 }1407 }
1261 bool hasArraySlow(OutputStream &S) const override {1408 bool hasArraySlow(OutputBuffer &OB) const override {
1262 if (Printing)1409 if (Printing)
1263 return false;1410 return false;
1264 SwapAndRestore<bool> SavePrinting(Printing, true);1411 SwapAndRestore<bool> SavePrinting(Printing, true);
1265 return Ref->hasArray(S);1412 return Ref->hasArray(OB);
1266 }1413 }
1267 bool hasFunctionSlow(OutputStream &S) const override {1414 bool hasFunctionSlow(OutputBuffer &OB) const override {
1268 if (Printing)1415 if (Printing)
1269 return false;1416 return false;
1270 SwapAndRestore<bool> SavePrinting(Printing, true);1417 SwapAndRestore<bool> SavePrinting(Printing, true);
1271 return Ref->hasFunction(S);1418 return Ref->hasFunction(OB);
1272 }1419 }
1273 const Node *getSyntaxNode(OutputStream &S) const override {1420 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1274 if (Printing)1421 if (Printing)
1275 return this;1422 return this;
1276 SwapAndRestore<bool> SavePrinting(Printing, true);1423 SwapAndRestore<bool> SavePrinting(Printing, true);
1277 return Ref->getSyntaxNode(S);1424 return Ref->getSyntaxNode(OB);
1278 }1425 }
12791426
1280 void printLeft(OutputStream &S) const override {1427 void printLeft(OutputBuffer &OB) const override {
1281 if (Printing)1428 if (Printing)
1282 return;1429 return;
1283 SwapAndRestore<bool> SavePrinting(Printing, true);1430 SwapAndRestore<bool> SavePrinting(Printing, true);
1284 Ref->printLeft(S);1431 Ref->printLeft(OB);
1285 }1432 }
1286 void printRight(OutputStream &S) const override {1433 void printRight(OutputBuffer &OB) const override {
1287 if (Printing)1434 if (Printing)
1288 return;1435 return;
1289 SwapAndRestore<bool> SavePrinting(Printing, true);1436 SwapAndRestore<bool> SavePrinting(Printing, true);
1290 Ref->printRight(S);1437 Ref->printRight(OB);
1291 }1438 }
1292};1439};
12931440
...@@ -1303,9 +1450,9 @@ struct NameWithTemplateArgs : Node {...@@ -1303,9 +1450,9 @@ struct NameWithTemplateArgs : Node {
13031450
1304 StringView getBaseName() const override { return Name->getBaseName(); }1451 StringView getBaseName() const override { return Name->getBaseName(); }
13051452
1306 void printLeft(OutputStream &S) const override {1453 void printLeft(OutputBuffer &OB) const override {
1307 Name->print(S);1454 Name->print(OB);
1308 TemplateArgs->print(S);1455 TemplateArgs->print(OB);
1309 }1456 }
1310};1457};
13111458
...@@ -1320,9 +1467,9 @@ public:...@@ -1320,9 +1467,9 @@ public:
13201467
1321 StringView getBaseName() const override { return Child->getBaseName(); }1468 StringView getBaseName() const override { return Child->getBaseName(); }
13221469
1323 void printLeft(OutputStream &S) const override {1470 void printLeft(OutputBuffer &OB) const override {
1324 S += "::";1471 OB += "::";
1325 Child->print(S);1472 Child->print(OB);
1326 }1473 }
1327};1474};
13281475
...@@ -1335,9 +1482,9 @@ struct StdQualifiedName : Node {...@@ -1335,9 +1482,9 @@ struct StdQualifiedName : Node {
13351482
1336 StringView getBaseName() const override { return Child->getBaseName(); }1483 StringView getBaseName() const override { return Child->getBaseName(); }
13371484
1338 void printLeft(OutputStream &S) const override {1485 void printLeft(OutputBuffer &OB) const override {
1339 S += "std::";1486 OB += "std::";
1340 Child->print(S);1487 Child->print(OB);
1341 }1488 }
1342};1489};
13431490
...@@ -1377,26 +1524,26 @@ public:...@@ -1377,26 +1524,26 @@ public:
1377 DEMANGLE_UNREACHABLE;1524 DEMANGLE_UNREACHABLE;
1378 }1525 }
13791526
1380 void printLeft(OutputStream &S) const override {1527 void printLeft(OutputBuffer &OB) const override {
1381 switch (SSK) {1528 switch (SSK) {
1382 case SpecialSubKind::allocator:1529 case SpecialSubKind::allocator:
1383 S += "std::allocator";1530 OB += "std::allocator";
1384 break;1531 break;
1385 case SpecialSubKind::basic_string:1532 case SpecialSubKind::basic_string:
1386 S += "std::basic_string";1533 OB += "std::basic_string";
1387 break;1534 break;
1388 case SpecialSubKind::string:1535 case SpecialSubKind::string:
1389 S += "std::basic_string<char, std::char_traits<char>, "1536 OB += "std::basic_string<char, std::char_traits<char>, "
1390 "std::allocator<char> >";1537 "std::allocator<char> >";
1391 break;1538 break;
1392 case SpecialSubKind::istream:1539 case SpecialSubKind::istream:
1393 S += "std::basic_istream<char, std::char_traits<char> >";1540 OB += "std::basic_istream<char, std::char_traits<char> >";
1394 break;1541 break;
1395 case SpecialSubKind::ostream:1542 case SpecialSubKind::ostream:
1396 S += "std::basic_ostream<char, std::char_traits<char> >";1543 OB += "std::basic_ostream<char, std::char_traits<char> >";
1397 break;1544 break;
1398 case SpecialSubKind::iostream:1545 case SpecialSubKind::iostream:
1399 S += "std::basic_iostream<char, std::char_traits<char> >";1546 OB += "std::basic_iostream<char, std::char_traits<char> >";
1400 break;1547 break;
1401 }1548 }
1402 }1549 }
...@@ -1429,25 +1576,25 @@ public:...@@ -1429,25 +1576,25 @@ public:
1429 DEMANGLE_UNREACHABLE;1576 DEMANGLE_UNREACHABLE;
1430 }1577 }
14311578
1432 void printLeft(OutputStream &S) const override {1579 void printLeft(OutputBuffer &OB) const override {
1433 switch (SSK) {1580 switch (SSK) {
1434 case SpecialSubKind::allocator:1581 case SpecialSubKind::allocator:
1435 S += "std::allocator";1582 OB += "std::allocator";
1436 break;1583 break;
1437 case SpecialSubKind::basic_string:1584 case SpecialSubKind::basic_string:
1438 S += "std::basic_string";1585 OB += "std::basic_string";
1439 break;1586 break;
1440 case SpecialSubKind::string:1587 case SpecialSubKind::string:
1441 S += "std::string";1588 OB += "std::string";
1442 break;1589 break;
1443 case SpecialSubKind::istream:1590 case SpecialSubKind::istream:
1444 S += "std::istream";1591 OB += "std::istream";
1445 break;1592 break;
1446 case SpecialSubKind::ostream:1593 case SpecialSubKind::ostream:
1447 S += "std::ostream";1594 OB += "std::ostream";
1448 break;1595 break;
1449 case SpecialSubKind::iostream:1596 case SpecialSubKind::iostream:
1450 S += "std::iostream";1597 OB += "std::iostream";
1451 break;1598 break;
1452 }1599 }
1453 }1600 }
...@@ -1465,10 +1612,10 @@ public:...@@ -1465,10 +1612,10 @@ public:
14651612
1466 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }1613 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
14671614
1468 void printLeft(OutputStream &S) const override {1615 void printLeft(OutputBuffer &OB) const override {
1469 if (IsDtor)1616 if (IsDtor)
1470 S += "~";1617 OB += "~";
1471 S += Basename->getBaseName();1618 OB += Basename->getBaseName();
1472 }1619 }
1473};1620};
14741621
...@@ -1480,9 +1627,9 @@ public:...@@ -1480,9 +1627,9 @@ public:
14801627
1481 template<typename Fn> void match(Fn F) const { F(Base); }1628 template<typename Fn> void match(Fn F) const { F(Base); }
14821629
1483 void printLeft(OutputStream &S) const override {1630 void printLeft(OutputBuffer &OB) const override {
1484 S += "~";1631 OB += "~";
1485 Base->printLeft(S);1632 Base->printLeft(OB);
1486 }1633 }
1487};1634};
14881635
...@@ -1494,10 +1641,10 @@ public:...@@ -1494,10 +1641,10 @@ public:
14941641
1495 template<typename Fn> void match(Fn F) const { F(Count); }1642 template<typename Fn> void match(Fn F) const { F(Count); }
14961643
1497 void printLeft(OutputStream &S) const override {1644 void printLeft(OutputBuffer &OB) const override {
1498 S += "'unnamed";1645 OB += "'unnamed";
1499 S += Count;1646 OB += Count;
1500 S += "\'";1647 OB += "\'";
1501 }1648 }
1502};1649};
15031650
...@@ -1516,22 +1663,22 @@ public:...@@ -1516,22 +1663,22 @@ public:
1516 F(TemplateParams, Params, Count);1663 F(TemplateParams, Params, Count);
1517 }1664 }
15181665
1519 void printDeclarator(OutputStream &S) const {1666 void printDeclarator(OutputBuffer &OB) const {
1520 if (!TemplateParams.empty()) {1667 if (!TemplateParams.empty()) {
1521 S += "<";1668 OB += "<";
1522 TemplateParams.printWithComma(S);1669 TemplateParams.printWithComma(OB);
1523 S += ">";1670 OB += ">";
1524 }1671 }
1525 S += "(";1672 OB += "(";
1526 Params.printWithComma(S);1673 Params.printWithComma(OB);
1527 S += ")";1674 OB += ")";
1528 }1675 }
15291676
1530 void printLeft(OutputStream &S) const override {1677 void printLeft(OutputBuffer &OB) const override {
1531 S += "\'lambda";1678 OB += "\'lambda";
1532 S += Count;1679 OB += Count;
1533 S += "\'";1680 OB += "\'";
1534 printDeclarator(S);1681 printDeclarator(OB);
1535 }1682 }
1536};1683};
15371684
...@@ -1543,10 +1690,10 @@ public:...@@ -1543,10 +1690,10 @@ public:
15431690
1544 template<typename Fn> void match(Fn F) const { F(Bindings); }1691 template<typename Fn> void match(Fn F) const { F(Bindings); }
15451692
1546 void printLeft(OutputStream &S) const override {1693 void printLeft(OutputBuffer &OB) const override {
1547 S += '[';1694 OB += '[';
1548 Bindings.printWithComma(S);1695 Bindings.printWithComma(OB);
1549 S += ']';1696 OB += ']';
1550 }1697 }
1551};1698};
15521699
...@@ -1564,22 +1711,22 @@ public:...@@ -1564,22 +1711,22 @@ public:
15641711
1565 template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); }1712 template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); }
15661713
1567 void printLeft(OutputStream &S) const override {1714 void printLeft(OutputBuffer &OB) const override {
1568 // might be a template argument expression, then we need to disambiguate1715 // might be a template argument expression, then we need to disambiguate
1569 // with parens.1716 // with parens.
1570 if (InfixOperator == ">")1717 if (InfixOperator == ">")
1571 S += "(";1718 OB += "(";
15721719
1573 S += "(";1720 OB += "(";
1574 LHS->print(S);1721 LHS->print(OB);
1575 S += ") ";1722 OB += ") ";
1576 S += InfixOperator;1723 OB += InfixOperator;
1577 S += " (";1724 OB += " (";
1578 RHS->print(S);1725 RHS->print(OB);
1579 S += ")";1726 OB += ")";
15801727
1581 if (InfixOperator == ">")1728 if (InfixOperator == ">")
1582 S += ")";1729 OB += ")";
1583 }1730 }
1584};1731};
15851732
...@@ -1593,12 +1740,12 @@ public:...@@ -1593,12 +1740,12 @@ public:
15931740
1594 template<typename Fn> void match(Fn F) const { F(Op1, Op2); }1741 template<typename Fn> void match(Fn F) const { F(Op1, Op2); }
15951742
1596 void printLeft(OutputStream &S) const override {1743 void printLeft(OutputBuffer &OB) const override {
1597 S += "(";1744 OB += "(";
1598 Op1->print(S);1745 Op1->print(OB);
1599 S += ")[";1746 OB += ")[";
1600 Op2->print(S);1747 Op2->print(OB);
1601 S += "]";1748 OB += "]";
1602 }1749 }
1603};1750};
16041751
...@@ -1612,11 +1759,11 @@ public:...@@ -1612,11 +1759,11 @@ public:
16121759
1613 template<typename Fn> void match(Fn F) const { F(Child, Operator); }1760 template<typename Fn> void match(Fn F) const { F(Child, Operator); }
16141761
1615 void printLeft(OutputStream &S) const override {1762 void printLeft(OutputBuffer &OB) const override {
1616 S += "(";1763 OB += "(";
1617 Child->print(S);1764 Child->print(OB);
1618 S += ")";1765 OB += ")";
1619 S += Operator;1766 OB += Operator;
1620 }1767 }
1621};1768};
16221769
...@@ -1631,14 +1778,14 @@ public:...@@ -1631,14 +1778,14 @@ public:
16311778
1632 template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); }1779 template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); }
16331780
1634 void printLeft(OutputStream &S) const override {1781 void printLeft(OutputBuffer &OB) const override {
1635 S += "(";1782 OB += "(";
1636 Cond->print(S);1783 Cond->print(OB);
1637 S += ") ? (";1784 OB += ") ? (";
1638 Then->print(S);1785 Then->print(OB);
1639 S += ") : (";1786 OB += ") : (";
1640 Else->print(S);1787 Else->print(OB);
1641 S += ")";1788 OB += ")";
1642 }1789 }
1643};1790};
16441791
...@@ -1653,10 +1800,10 @@ public:...@@ -1653,10 +1800,10 @@ public:
16531800
1654 template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); }1801 template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); }
16551802
1656 void printLeft(OutputStream &S) const override {1803 void printLeft(OutputBuffer &OB) const override {
1657 LHS->print(S);1804 LHS->print(OB);
1658 S += Kind;1805 OB += Kind;
1659 RHS->print(S);1806 RHS->print(OB);
1660 }1807 }
1661};1808};
16621809
...@@ -1677,20 +1824,20 @@ public:...@@ -1677,20 +1824,20 @@ public:
1677 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);1824 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1678 }1825 }
16791826
1680 void printLeft(OutputStream &S) const override {1827 void printLeft(OutputBuffer &OB) const override {
1681 SubExpr->print(S);1828 SubExpr->print(OB);
1682 S += ".<";1829 OB += ".<";
1683 Type->print(S);1830 Type->print(OB);
1684 S += " at offset ";1831 OB += " at offset ";
1685 if (Offset.empty()) {1832 if (Offset.empty()) {
1686 S += "0";1833 OB += "0";
1687 } else if (Offset[0] == 'n') {1834 } else if (Offset[0] == 'n') {
1688 S += "-";1835 OB += "-";
1689 S += Offset.dropFront();1836 OB += Offset.dropFront();
1690 } else {1837 } else {
1691 S += Offset;1838 OB += Offset;
1692 }1839 }
1693 S += ">";1840 OB += ">";
1694 }1841 }
1695};1842};
16961843
...@@ -1706,10 +1853,10 @@ public:...@@ -1706,10 +1853,10 @@ public:
17061853
1707 template<typename Fn> void match(Fn F) const { F(Prefix, Infix, Postfix); }1854 template<typename Fn> void match(Fn F) const { F(Prefix, Infix, Postfix); }
17081855
1709 void printLeft(OutputStream &S) const override {1856 void printLeft(OutputBuffer &OB) const override {
1710 S += Prefix;1857 OB += Prefix;
1711 Infix->print(S);1858 Infix->print(OB);
1712 S += Postfix;1859 OB += Postfix;
1713 }1860 }
1714};1861};
17151862
...@@ -1725,13 +1872,13 @@ public:...@@ -1725,13 +1872,13 @@ public:
17251872
1726 template<typename Fn> void match(Fn F) const { F(CastKind, To, From); }1873 template<typename Fn> void match(Fn F) const { F(CastKind, To, From); }
17271874
1728 void printLeft(OutputStream &S) const override {1875 void printLeft(OutputBuffer &OB) const override {
1729 S += CastKind;1876 OB += CastKind;
1730 S += "<";1877 OB += "<";
1731 To->printLeft(S);1878 To->printLeft(OB);
1732 S += ">(";1879 OB += ">(";
1733 From->printLeft(S);1880 From->printLeft(OB);
1734 S += ")";1881 OB += ")";
1735 }1882 }
1736};1883};
17371884
...@@ -1744,11 +1891,11 @@ public:...@@ -1744,11 +1891,11 @@ public:
17441891
1745 template<typename Fn> void match(Fn F) const { F(Pack); }1892 template<typename Fn> void match(Fn F) const { F(Pack); }
17461893
1747 void printLeft(OutputStream &S) const override {1894 void printLeft(OutputBuffer &OB) const override {
1748 S += "sizeof...(";1895 OB += "sizeof...(";
1749 ParameterPackExpansion PPE(Pack);1896 ParameterPackExpansion PPE(Pack);
1750 PPE.printLeft(S);1897 PPE.printLeft(OB);
1751 S += ")";1898 OB += ")";
1752 }1899 }
1753};1900};
17541901
...@@ -1762,11 +1909,11 @@ public:...@@ -1762,11 +1909,11 @@ public:
17621909
1763 template<typename Fn> void match(Fn F) const { F(Callee, Args); }1910 template<typename Fn> void match(Fn F) const { F(Callee, Args); }
17641911
1765 void printLeft(OutputStream &S) const override {1912 void printLeft(OutputBuffer &OB) const override {
1766 Callee->print(S);1913 Callee->print(OB);
1767 S += "(";1914 OB += "(";
1768 Args.printWithComma(S);1915 Args.printWithComma(OB);
1769 S += ")";1916 OB += ")";
1770 }1917 }
1771};1918};
17721919
...@@ -1787,25 +1934,24 @@ public:...@@ -1787,25 +1934,24 @@ public:
1787 F(ExprList, Type, InitList, IsGlobal, IsArray);1934 F(ExprList, Type, InitList, IsGlobal, IsArray);
1788 }1935 }
17891936
1790 void printLeft(OutputStream &S) const override {1937 void printLeft(OutputBuffer &OB) const override {
1791 if (IsGlobal)1938 if (IsGlobal)
1792 S += "::operator ";1939 OB += "::operator ";
1793 S += "new";1940 OB += "new";
1794 if (IsArray)1941 if (IsArray)
1795 S += "[]";1942 OB += "[]";
1796 S += ' ';1943 OB += ' ';
1797 if (!ExprList.empty()) {1944 if (!ExprList.empty()) {
1798 S += "(";1945 OB += "(";
1799 ExprList.printWithComma(S);1946 ExprList.printWithComma(OB);
1800 S += ")";1947 OB += ")";
1801 }1948 }
1802 Type->print(S);1949 Type->print(OB);
1803 if (!InitList.empty()) {1950 if (!InitList.empty()) {
1804 S += "(";1951 OB += "(";
1805 InitList.printWithComma(S);1952 InitList.printWithComma(OB);
1806 S += ")";1953 OB += ")";
1807 }1954 }
1808
1809 }1955 }
1810};1956};
18111957
...@@ -1820,13 +1966,13 @@ public:...@@ -1820,13 +1966,13 @@ public:
18201966
1821 template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); }1967 template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); }
18221968
1823 void printLeft(OutputStream &S) const override {1969 void printLeft(OutputBuffer &OB) const override {
1824 if (IsGlobal)1970 if (IsGlobal)
1825 S += "::";1971 OB += "::";
1826 S += "delete";1972 OB += "delete";
1827 if (IsArray)1973 if (IsArray)
1828 S += "[] ";1974 OB += "[] ";
1829 Op->print(S);1975 Op->print(OB);
1830 }1976 }
1831};1977};
18321978
...@@ -1840,11 +1986,11 @@ public:...@@ -1840,11 +1986,11 @@ public:
18401986
1841 template<typename Fn> void match(Fn F) const { F(Prefix, Child); }1987 template<typename Fn> void match(Fn F) const { F(Prefix, Child); }
18421988
1843 void printLeft(OutputStream &S) const override {1989 void printLeft(OutputBuffer &OB) const override {
1844 S += Prefix;1990 OB += Prefix;
1845 S += "(";1991 OB += "(";
1846 Child->print(S);1992 Child->print(OB);
1847 S += ")";1993 OB += ")";
1848 }1994 }
1849};1995};
18501996
...@@ -1856,9 +2002,9 @@ public:...@@ -1856,9 +2002,9 @@ public:
18562002
1857 template<typename Fn> void match(Fn F) const { F(Number); }2003 template<typename Fn> void match(Fn F) const { F(Number); }
18582004
1859 void printLeft(OutputStream &S) const override {2005 void printLeft(OutputBuffer &OB) const override {
1860 S += "fp";2006 OB += "fp";
1861 S += Number;2007 OB += Number;
1862 }2008 }
1863};2009};
18642010
...@@ -1872,12 +2018,12 @@ public:...@@ -1872,12 +2018,12 @@ public:
18722018
1873 template<typename Fn> void match(Fn F) const { F(Type, Expressions); }2019 template<typename Fn> void match(Fn F) const { F(Type, Expressions); }
18742020
1875 void printLeft(OutputStream &S) const override {2021 void printLeft(OutputBuffer &OB) const override {
1876 S += "(";2022 OB += "(";
1877 Type->print(S);2023 Type->print(OB);
1878 S += ")(";2024 OB += ")(";
1879 Expressions.printWithComma(S);2025 Expressions.printWithComma(OB);
1880 S += ")";2026 OB += ")";
1881 }2027 }
1882};2028};
18832029
...@@ -1894,12 +2040,12 @@ public:...@@ -1894,12 +2040,12 @@ public:
18942040
1895 template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); }2041 template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); }
18962042
1897 void printLeft(OutputStream &S) const override {2043 void printLeft(OutputBuffer &OB) const override {
1898 S += "(";2044 OB += "(";
1899 Type->print(S);2045 Type->print(OB);
1900 S += ")(";2046 OB += ")(";
1901 SubExpr->print(S);2047 SubExpr->print(OB);
1902 S += ")";2048 OB += ")";
1903 }2049 }
1904};2050};
19052051
...@@ -1912,12 +2058,12 @@ public:...@@ -1912,12 +2058,12 @@ public:
19122058
1913 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }2059 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
19142060
1915 void printLeft(OutputStream &S) const override {2061 void printLeft(OutputBuffer &OB) const override {
1916 if (Ty)2062 if (Ty)
1917 Ty->print(S);2063 Ty->print(OB);
1918 S += '{';2064 OB += '{';
1919 Inits.printWithComma(S);2065 Inits.printWithComma(OB);
1920 S += '}';2066 OB += '}';
1921 }2067 }
1922};2068};
19232069
...@@ -1931,18 +2077,18 @@ public:...@@ -1931,18 +2077,18 @@ public:
19312077
1932 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }2078 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
19332079
1934 void printLeft(OutputStream &S) const override {2080 void printLeft(OutputBuffer &OB) const override {
1935 if (IsArray) {2081 if (IsArray) {
1936 S += '[';2082 OB += '[';
1937 Elem->print(S);2083 Elem->print(OB);
1938 S += ']';2084 OB += ']';
1939 } else {2085 } else {
1940 S += '.';2086 OB += '.';
1941 Elem->print(S);2087 Elem->print(OB);
1942 }2088 }
1943 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)2089 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1944 S += " = ";2090 OB += " = ";
1945 Init->print(S);2091 Init->print(OB);
1946 }2092 }
1947};2093};
19482094
...@@ -1956,15 +2102,15 @@ public:...@@ -1956,15 +2102,15 @@ public:
19562102
1957 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }2103 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
19582104
1959 void printLeft(OutputStream &S) const override {2105 void printLeft(OutputBuffer &OB) const override {
1960 S += '[';2106 OB += '[';
1961 First->print(S);2107 First->print(OB);
1962 S += " ... ";2108 OB += " ... ";
1963 Last->print(S);2109 Last->print(OB);
1964 S += ']';2110 OB += ']';
1965 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)2111 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1966 S += " = ";2112 OB += " = ";
1967 Init->print(S);2113 Init->print(OB);
1968 }2114 }
1969};2115};
19702116
...@@ -1983,43 +2129,43 @@ public:...@@ -1983,43 +2129,43 @@ public:
1983 F(IsLeftFold, OperatorName, Pack, Init);2129 F(IsLeftFold, OperatorName, Pack, Init);
1984 }2130 }
19852131
1986 void printLeft(OutputStream &S) const override {2132 void printLeft(OutputBuffer &OB) const override {
1987 auto PrintPack = [&] {2133 auto PrintPack = [&] {
1988 S += '(';2134 OB += '(';
1989 ParameterPackExpansion(Pack).print(S);2135 ParameterPackExpansion(Pack).print(OB);
1990 S += ')';2136 OB += ')';
1991 };2137 };
19922138
1993 S += '(';2139 OB += '(';
19942140
1995 if (IsLeftFold) {2141 if (IsLeftFold) {
1996 // init op ... op pack2142 // init op ... op pack
1997 if (Init != nullptr) {2143 if (Init != nullptr) {
1998 Init->print(S);2144 Init->print(OB);
1999 S += ' ';2145 OB += ' ';
2000 S += OperatorName;2146 OB += OperatorName;
2001 S += ' ';2147 OB += ' ';
2002 }2148 }
2003 // ... op pack2149 // ... op pack
2004 S += "... ";2150 OB += "... ";
2005 S += OperatorName;2151 OB += OperatorName;
2006 S += ' ';2152 OB += ' ';
2007 PrintPack();2153 PrintPack();
2008 } else { // !IsLeftFold2154 } else { // !IsLeftFold
2009 // pack op ...2155 // pack op ...
2010 PrintPack();2156 PrintPack();
2011 S += ' ';2157 OB += ' ';
2012 S += OperatorName;2158 OB += OperatorName;
2013 S += " ...";2159 OB += " ...";
2014 // pack op ... op init2160 // pack op ... op init
2015 if (Init != nullptr) {2161 if (Init != nullptr) {
2016 S += ' ';2162 OB += ' ';
2017 S += OperatorName;2163 OB += OperatorName;
2018 S += ' ';2164 OB += ' ';
2019 Init->print(S);2165 Init->print(OB);
2020 }2166 }
2021 }2167 }
2022 S += ')';2168 OB += ')';
2023 }2169 }
2024};2170};
20252171
...@@ -2031,9 +2177,9 @@ public:...@@ -2031,9 +2177,9 @@ public:
20312177
2032 template<typename Fn> void match(Fn F) const { F(Op); }2178 template<typename Fn> void match(Fn F) const { F(Op); }
20332179
2034 void printLeft(OutputStream &S) const override {2180 void printLeft(OutputBuffer &OB) const override {
2035 S += "throw ";2181 OB += "throw ";
2036 Op->print(S);2182 Op->print(OB);
2037 }2183 }
2038};2184};
20392185
...@@ -2045,8 +2191,8 @@ public:...@@ -2045,8 +2191,8 @@ public:
20452191
2046 template<typename Fn> void match(Fn F) const { F(Value); }2192 template<typename Fn> void match(Fn F) const { F(Value); }
20472193
2048 void printLeft(OutputStream &S) const override {2194 void printLeft(OutputBuffer &OB) const override {
2049 S += Value ? StringView("true") : StringView("false");2195 OB += Value ? StringView("true") : StringView("false");
2050 }2196 }
2051};2197};
20522198
...@@ -2058,10 +2204,10 @@ public:...@@ -2058,10 +2204,10 @@ public:
20582204
2059 template<typename Fn> void match(Fn F) const { F(Type); }2205 template<typename Fn> void match(Fn F) const { F(Type); }
20602206
2061 void printLeft(OutputStream &S) const override {2207 void printLeft(OutputBuffer &OB) const override {
2062 S += "\"<";2208 OB += "\"<";
2063 Type->print(S);2209 Type->print(OB);
2064 S += ">\"";2210 OB += ">\"";
2065 }2211 }
2066};2212};
20672213
...@@ -2073,11 +2219,11 @@ public:...@@ -2073,11 +2219,11 @@ public:
20732219
2074 template<typename Fn> void match(Fn F) const { F(Type); }2220 template<typename Fn> void match(Fn F) const { F(Type); }
20752221
2076 void printLeft(OutputStream &S) const override {2222 void printLeft(OutputBuffer &OB) const override {
2077 S += "[]";2223 OB += "[]";
2078 if (Type->getKind() == KClosureTypeName)2224 if (Type->getKind() == KClosureTypeName)
2079 static_cast<const ClosureTypeName *>(Type)->printDeclarator(S);2225 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2080 S += "{...}";2226 OB += "{...}";
2081 }2227 }
2082};2228};
20832229
...@@ -2092,15 +2238,15 @@ public:...@@ -2092,15 +2238,15 @@ public:
20922238
2093 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }2239 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
20942240
2095 void printLeft(OutputStream &S) const override {2241 void printLeft(OutputBuffer &OB) const override {
2096 S << "(";2242 OB << "(";
2097 Ty->print(S);2243 Ty->print(OB);
2098 S << ")";2244 OB << ")";
20992245
2100 if (Integer[0] == 'n')2246 if (Integer[0] == 'n')
2101 S << "-" << Integer.dropFront(1);2247 OB << "-" << Integer.dropFront(1);
2102 else2248 else
2103 S << Integer;2249 OB << Integer;
2104 }2250 }
2105};2251};
21062252
...@@ -2114,21 +2260,21 @@ public:...@@ -2114,21 +2260,21 @@ public:
21142260
2115 template<typename Fn> void match(Fn F) const { F(Type, Value); }2261 template<typename Fn> void match(Fn F) const { F(Type, Value); }
21162262
2117 void printLeft(OutputStream &S) const override {2263 void printLeft(OutputBuffer &OB) const override {
2118 if (Type.size() > 3) {2264 if (Type.size() > 3) {
2119 S += "(";2265 OB += "(";
2120 S += Type;2266 OB += Type;
2121 S += ")";2267 OB += ")";
2122 }2268 }
21232269
2124 if (Value[0] == 'n') {2270 if (Value[0] == 'n') {
2125 S += "-";2271 OB += "-";
2126 S += Value.dropFront(1);2272 OB += Value.dropFront(1);
2127 } else2273 } else
2128 S += Value;2274 OB += Value;
21292275
2130 if (Type.size() <= 3)2276 if (Type.size() <= 3)
2131 S += Type;2277 OB += Type;
2132 }2278 }
2133};2279};
21342280
...@@ -2158,7 +2304,7 @@ public:...@@ -2158,7 +2304,7 @@ public:
21582304
2159 template<typename Fn> void match(Fn F) const { F(Contents); }2305 template<typename Fn> void match(Fn F) const { F(Contents); }
21602306
2161 void printLeft(OutputStream &s) const override {2307 void printLeft(OutputBuffer &OB) const override {
2162 const char *first = Contents.begin();2308 const char *first = Contents.begin();
2163 const char *last = Contents.end() + 1;2309 const char *last = Contents.end() + 1;
21642310
...@@ -2184,7 +2330,7 @@ public:...@@ -2184,7 +2330,7 @@ public:
2184#endif2330#endif
2185 char num[FloatData<Float>::max_demangled_size] = {0};2331 char num[FloatData<Float>::max_demangled_size] = {0};
2186 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);2332 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
2187 s += StringView(num, num + n);2333 OB += StringView(num, num + n);
2188 }2334 }
2189 }2335 }
2190};2336};
...@@ -2217,125 +2363,6 @@ FOR_EACH_NODE_KIND(SPECIALIZATION)...@@ -2217,125 +2363,6 @@ FOR_EACH_NODE_KIND(SPECIALIZATION)
22172363
2218#undef FOR_EACH_NODE_KIND2364#undef FOR_EACH_NODE_KIND
22192365
2220template <class T, size_t N>
2221class PODSmallVector {
2222 static_assert(std::is_pod<T>::value,
2223 "T is required to be a plain old data type");
2224
2225 T* First = nullptr;
2226 T* Last = nullptr;
2227 T* Cap = nullptr;
2228 T Inline[N] = {0};
2229
2230 bool isInline() const { return First == Inline; }
2231
2232 void clearInline() {
2233 First = Inline;
2234 Last = Inline;
2235 Cap = Inline + N;
2236 }
2237
2238 void reserve(size_t NewCap) {
2239 size_t S = size();
2240 if (isInline()) {
2241 auto* Tmp = static_cast<T*>(std::malloc(NewCap * sizeof(T)));
2242 if (Tmp == nullptr)
2243 std::terminate();
2244 std::copy(First, Last, Tmp);
2245 First = Tmp;
2246 } else {
2247 First = static_cast<T*>(std::realloc(First, NewCap * sizeof(T)));
2248 if (First == nullptr)
2249 std::terminate();
2250 }
2251 Last = First + S;
2252 Cap = First + NewCap;
2253 }
2254
2255public:
2256 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
2257
2258 PODSmallVector(const PODSmallVector&) = delete;
2259 PODSmallVector& operator=(const PODSmallVector&) = delete;
2260
2261 PODSmallVector(PODSmallVector&& Other) : PODSmallVector() {
2262 if (Other.isInline()) {
2263 std::copy(Other.begin(), Other.end(), First);
2264 Last = First + Other.size();
2265 Other.clear();
2266 return;
2267 }
2268
2269 First = Other.First;
2270 Last = Other.Last;
2271 Cap = Other.Cap;
2272 Other.clearInline();
2273 }
2274
2275 PODSmallVector& operator=(PODSmallVector&& Other) {
2276 if (Other.isInline()) {
2277 if (!isInline()) {
2278 std::free(First);
2279 clearInline();
2280 }
2281 std::copy(Other.begin(), Other.end(), First);
2282 Last = First + Other.size();
2283 Other.clear();
2284 return *this;
2285 }
2286
2287 if (isInline()) {
2288 First = Other.First;
2289 Last = Other.Last;
2290 Cap = Other.Cap;
2291 Other.clearInline();
2292 return *this;
2293 }
2294
2295 std::swap(First, Other.First);
2296 std::swap(Last, Other.Last);
2297 std::swap(Cap, Other.Cap);
2298 Other.clear();
2299 return *this;
2300 }
2301
2302 void push_back(const T& Elem) {
2303 if (Last == Cap)
2304 reserve(size() * 2);
2305 *Last++ = Elem;
2306 }
2307
2308 void pop_back() {
2309 assert(Last != First && "Popping empty vector!");
2310 --Last;
2311 }
2312
2313 void dropBack(size_t Index) {
2314 assert(Index <= size() && "dropBack() can't expand!");
2315 Last = First + Index;
2316 }
2317
2318 T* begin() { return First; }
2319 T* end() { return Last; }
2320
2321 bool empty() const { return First == Last; }
2322 size_t size() const { return static_cast<size_t>(Last - First); }
2323 T& back() {
2324 assert(Last != First && "Calling back() on empty vector!");
2325 return *(Last - 1);
2326 }
2327 T& operator[](size_t Index) {
2328 assert(Index < size() && "Invalid access!");
2329 return *(begin() + Index);
2330 }
2331 void clear() { Last = First; }
2332
2333 ~PODSmallVector() {
2334 if (!isInline())
2335 std::free(First);
2336 }
2337};
2338
2339template <typename Derived, typename Alloc> struct AbstractManglingParser {2366template <typename Derived, typename Alloc> struct AbstractManglingParser {
2340 const char *First;2367 const char *First;
2341 const char *Last;2368 const char *Last;
...@@ -2450,7 +2477,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2450,7 +2477,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
24502477
2451 char consume() { return First != Last ? *First++ : '\0'; }2478 char consume() { return First != Last ? *First++ : '\0'; }
24522479
2453 char look(unsigned Lookahead = 0) {2480 char look(unsigned Lookahead = 0) const {
2454 if (static_cast<size_t>(Last - First) <= Lookahead)2481 if (static_cast<size_t>(Last - First) <= Lookahead)
2455 return '\0';2482 return '\0';
2456 return First[Lookahead];2483 return First[Lookahead];
...@@ -2568,34 +2595,38 @@ Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {...@@ -2568,34 +2595,38 @@ Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
2568 if (look() == 'Z')2595 if (look() == 'Z')
2569 return getDerived().parseLocalName(State);2596 return getDerived().parseLocalName(State);
25702597
2571 // ::= <unscoped-template-name> <template-args>2598 Node *Result = nullptr;
2572 if (look() == 'S' && look(1) != 't') {2599 bool IsSubst = look() == 'S' && look(1) != 't';
2573 Node *S = getDerived().parseSubstitution();2600 if (IsSubst) {
2574 if (S == nullptr)2601 // A substitution must lead to:
2575 return nullptr;2602 // ::= <unscoped-template-name> <template-args>
2576 if (look() != 'I')2603 Result = getDerived().parseSubstitution();
2577 return nullptr;2604 } else {
2578 Node *TA = getDerived().parseTemplateArgs(State != nullptr);2605 // An unscoped name can be one of:
2579 if (TA == nullptr)2606 // ::= <unscoped-name>
2580 return nullptr;2607 // ::= <unscoped-template-name> <template-args>
2581 if (State) State->EndsWithTemplateArgs = true;2608 Result = getDerived().parseUnscopedName(State);
2582 return make<NameWithTemplateArgs>(S, TA);
2583 }2609 }
25842610 if (Result == nullptr)
2585 Node *N = getDerived().parseUnscopedName(State);
2586 if (N == nullptr)
2587 return nullptr;2611 return nullptr;
2588 // ::= <unscoped-template-name> <template-args>2612
2589 if (look() == 'I') {2613 if (look() == 'I') {
2590 Subs.push_back(N);2614 // ::= <unscoped-template-name> <template-args>
2615 if (!IsSubst)
2616 // An unscoped-template-name is substitutable.
2617 Subs.push_back(Result);
2591 Node *TA = getDerived().parseTemplateArgs(State != nullptr);2618 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
2592 if (TA == nullptr)2619 if (TA == nullptr)
2593 return nullptr;2620 return nullptr;
2594 if (State) State->EndsWithTemplateArgs = true;2621 if (State)
2595 return make<NameWithTemplateArgs>(N, TA);2622 State->EndsWithTemplateArgs = true;
2623 Result = make<NameWithTemplateArgs>(Result, TA);
2624 } else if (IsSubst) {
2625 // The substitution case must be followed by <template-args>.
2626 return nullptr;
2596 }2627 }
2597 // ::= <unscoped-name>2628
2598 return N;2629 return Result;
2599}2630}
26002631
2601// <local-name> := Z <function encoding> E <entity name> [<discriminator>]2632// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
...@@ -2640,13 +2671,17 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {...@@ -2640,13 +2671,17 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
2640template <typename Derived, typename Alloc>2671template <typename Derived, typename Alloc>
2641Node *2672Node *
2642AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {2673AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {
2643 if (consumeIf("StL") || consumeIf("St")) {2674 bool IsStd = consumeIf("St");
2644 Node *R = getDerived().parseUnqualifiedName(State);2675 if (IsStd)
2645 if (R == nullptr)2676 consumeIf('L');
2646 return nullptr;2677
2647 return make<StdQualifiedName>(R);2678 Node *Result = getDerived().parseUnqualifiedName(State);
2648 }2679 if (Result == nullptr)
2649 return getDerived().parseUnqualifiedName(State);2680 return nullptr;
2681 if (IsStd)
2682 Result = make<StdQualifiedName>(Result);
2683
2684 return Result;
2650}2685}
26512686
2652// <unqualified-name> ::= <operator-name> [abi-tags]2687// <unqualified-name> ::= <operator-name> [abi-tags]
...@@ -3884,6 +3919,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {...@@ -3884,6 +3919,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
3884 case 'h':3919 case 'h':
3885 First += 2;3920 First += 2;
3886 return make<NameType>("half");3921 return make<NameType>("half");
3922 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3923 case 'F': {
3924 First += 2;
3925 Node *DimensionNumber = make<NameType>(parseNumber());
3926 if (!DimensionNumber)
3927 return nullptr;
3928 if (!consumeIf('_'))
3929 return nullptr;
3930 return make<BinaryFPType>(DimensionNumber);
3931 }
3887 // ::= Di # char32_t3932 // ::= Di # char32_t
3888 case 'i':3933 case 'i':
3889 First += 2;3934 First += 2;
...@@ -4031,9 +4076,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {...@@ -4031,9 +4076,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
4031 }4076 }
4032 // ::= <substitution> # See Compression below4077 // ::= <substitution> # See Compression below
4033 case 'S': {4078 case 'S': {
4034 if (look(1) && look(1) != 't') {4079 if (look(1) != 't') {
4035 Node *Sub = getDerived().parseSubstitution();4080 Result = getDerived().parseSubstitution();
4036 if (Sub == nullptr)4081 if (Result == nullptr)
4037 return nullptr;4082 return nullptr;
40384083
4039 // Sub could be either of:4084 // Sub could be either of:
...@@ -4050,13 +4095,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {...@@ -4050,13 +4095,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
4050 Node *TA = getDerived().parseTemplateArgs();4095 Node *TA = getDerived().parseTemplateArgs();
4051 if (TA == nullptr)4096 if (TA == nullptr)
4052 return nullptr;4097 return nullptr;
4053 Result = make<NameWithTemplateArgs>(Sub, TA);4098 Result = make<NameWithTemplateArgs>(Result, TA);
4054 break;4099 } else {
4100 // If all we parsed was a substitution, don't re-insert into the
4101 // substitution table.
4102 return Result;
4055 }4103 }
40564104 break;
4057 // If all we parsed was a substitution, don't re-insert into the
4058 // substitution table.
4059 return Sub;
4060 }4105 }
4061 DEMANGLE_FALLTHROUGH;4106 DEMANGLE_FALLTHROUGH;
4062 }4107 }
...@@ -5404,38 +5449,35 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {...@@ -5404,38 +5449,35 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
5404 if (!consumeIf('S'))5449 if (!consumeIf('S'))
5405 return nullptr;5450 return nullptr;
54065451
5407 if (std::islower(look())) {5452 if (look() >= 'a' && look() <= 'z') {
5408 Node *SpecialSub;5453 SpecialSubKind Kind;
5409 switch (look()) {5454 switch (look()) {
5410 case 'a':5455 case 'a':
5411 ++First;5456 Kind = SpecialSubKind::allocator;
5412 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::allocator);
5413 break;5457 break;
5414 case 'b':5458 case 'b':
5415 ++First;5459 Kind = SpecialSubKind::basic_string;
5416 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::basic_string);
5417 break;5460 break;
5418 case 's':5461 case 'd':
5419 ++First;5462 Kind = SpecialSubKind::iostream;
5420 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::string);
5421 break;5463 break;
5422 case 'i':5464 case 'i':
5423 ++First;5465 Kind = SpecialSubKind::istream;
5424 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::istream);
5425 break;5466 break;
5426 case 'o':5467 case 'o':
5427 ++First;5468 Kind = SpecialSubKind::ostream;
5428 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::ostream);
5429 break;5469 break;
5430 case 'd':5470 case 's':
5431 ++First;5471 Kind = SpecialSubKind::string;
5432 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::iostream);
5433 break;5472 break;
5434 default:5473 default:
5435 return nullptr;5474 return nullptr;
5436 }5475 }
5476 ++First;
5477 auto *SpecialSub = make<SpecialSubstitution>(Kind);
5437 if (!SpecialSub)5478 if (!SpecialSub)
5438 return nullptr;5479 return nullptr;
5480
5439 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>5481 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5440 // has ABI tags, the tags are appended to the substitution; the result is a5482 // has ABI tags, the tags are appended to the substitution; the result is a
5441 // substitutable component.5483 // substitutable component.
lib/libcxxabi/src/demangle/StringView.h+10-7
...@@ -7,6 +7,9 @@...@@ -7,6 +7,9 @@
7//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
8//8//
9// FIXME: Use std::string_view instead when we support C++17.9// FIXME: Use std::string_view instead when we support C++17.
10// There are two copies of this file in the source tree. The one under
11// libcxxabi is the original and the one under llvm is the copy. Use
12// cp-to-llvm.sh to update the copy. See README.txt for more details.
10//13//
11//===----------------------------------------------------------------------===//14//===----------------------------------------------------------------------===//
1215
...@@ -14,7 +17,6 @@...@@ -14,7 +17,6 @@
14#define DEMANGLE_STRINGVIEW_H17#define DEMANGLE_STRINGVIEW_H
1518
16#include "DemangleConfig.h"19#include "DemangleConfig.h"
17#include <algorithm>
18#include <cassert>20#include <cassert>
19#include <cstring>21#include <cstring>
2022
...@@ -38,15 +40,16 @@ public:...@@ -38,15 +40,16 @@ public:
3840
39 StringView substr(size_t Pos, size_t Len = npos) const {41 StringView substr(size_t Pos, size_t Len = npos) const {
40 assert(Pos <= size());42 assert(Pos <= size());
41 return StringView(begin() + Pos, std::min(Len, size() - Pos));43 if (Len > size() - Pos)
44 Len = size() - Pos;
45 return StringView(begin() + Pos, Len);
42 }46 }
4347
44 size_t find(char C, size_t From = 0) const {48 size_t find(char C, size_t From = 0) const {
45 size_t FindBegin = std::min(From, size());
46 // Avoid calling memchr with nullptr.49 // Avoid calling memchr with nullptr.
47 if (FindBegin < size()) {50 if (From < size()) {
48 // Just forward to memchr, which is faster than a hand-rolled loop.51 // Just forward to memchr, which is faster than a hand-rolled loop.
49 if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))52 if (const void *P = ::memchr(First + From, C, size() - From))
50 return size_t(static_cast<const char *>(P) - First);53 return size_t(static_cast<const char *>(P) - First);
51 }54 }
52 return npos;55 return npos;
...@@ -98,7 +101,7 @@ public:...@@ -98,7 +101,7 @@ public:
98 bool startsWith(StringView Str) const {101 bool startsWith(StringView Str) const {
99 if (Str.size() > size())102 if (Str.size() > size())
100 return false;103 return false;
101 return std::equal(Str.begin(), Str.end(), begin());104 return std::strncmp(Str.begin(), begin(), Str.size()) == 0;
102 }105 }
103106
104 const char &operator[](size_t Idx) const { return *(begin() + Idx); }107 const char &operator[](size_t Idx) const { return *(begin() + Idx); }
...@@ -111,7 +114,7 @@ public:...@@ -111,7 +114,7 @@ public:
111114
112inline bool operator==(const StringView &LHS, const StringView &RHS) {115inline bool operator==(const StringView &LHS, const StringView &RHS) {
113 return LHS.size() == RHS.size() &&116 return LHS.size() == RHS.size() &&
114 std::equal(LHS.begin(), LHS.end(), RHS.begin());117 std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0;
115}118}
116119
117DEMANGLE_NAMESPACE_END120DEMANGLE_NAMESPACE_END
lib/libcxxabi/src/demangle/Utility.h+45-20
...@@ -6,7 +6,10 @@...@@ -6,7 +6,10 @@
6//6//
7//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
8//8//
9// Provide some utility classes for use in the demangler(s).9// Provide some utility classes for use in the demangler.
10// There are two copies of this file in the source tree. The one in libcxxabi
11// is the original and the one in llvm is the copy. Use cp-to-llvm.sh to update
12// the copy. See README.txt for more details.
10//13//
11//===----------------------------------------------------------------------===//14//===----------------------------------------------------------------------===//
1215
...@@ -14,17 +17,18 @@...@@ -14,17 +17,18 @@
14#define DEMANGLE_UTILITY_H17#define DEMANGLE_UTILITY_H
1518
16#include "StringView.h"19#include "StringView.h"
20#include <array>
17#include <cstdint>21#include <cstdint>
18#include <cstdlib>22#include <cstdlib>
19#include <cstring>23#include <cstring>
20#include <iterator>24#include <exception>
21#include <limits>25#include <limits>
2226
23DEMANGLE_NAMESPACE_BEGIN27DEMANGLE_NAMESPACE_BEGIN
2428
25// Stream that AST nodes write their string representation into after the AST29// Stream that AST nodes write their string representation into after the AST
26// has been parsed.30// has been parsed.
27class OutputStream {31class OutputBuffer {
28 char *Buffer = nullptr;32 char *Buffer = nullptr;
29 size_t CurrentPosition = 0;33 size_t CurrentPosition = 0;
30 size_t BufferCapacity = 0;34 size_t BufferCapacity = 0;
...@@ -48,8 +52,8 @@ class OutputStream {...@@ -48,8 +52,8 @@ class OutputStream {
48 return;52 return;
49 }53 }
5054
51 char Temp[21];55 std::array<char, 21> Temp;
52 char *TempPtr = std::end(Temp);56 char *TempPtr = Temp.data() + Temp.size();
5357
54 while (N) {58 while (N) {
55 *--TempPtr = char('0' + N % 10);59 *--TempPtr = char('0' + N % 10);
...@@ -59,13 +63,13 @@ class OutputStream {...@@ -59,13 +63,13 @@ class OutputStream {
59 // Add negative sign...63 // Add negative sign...
60 if (isNeg)64 if (isNeg)
61 *--TempPtr = '-';65 *--TempPtr = '-';
62 this->operator<<(StringView(TempPtr, std::end(Temp)));66 this->operator<<(StringView(TempPtr, Temp.data() + Temp.size()));
63 }67 }
6468
65public:69public:
66 OutputStream(char *StartBuf, size_t Size)70 OutputBuffer(char *StartBuf, size_t Size)
67 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}71 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
68 OutputStream() = default;72 OutputBuffer() = default;
69 void reset(char *Buffer_, size_t BufferCapacity_) {73 void reset(char *Buffer_, size_t BufferCapacity_) {
70 CurrentPosition = 0;74 CurrentPosition = 0;
71 Buffer = Buffer_;75 Buffer = Buffer_;
...@@ -77,7 +81,7 @@ public:...@@ -77,7 +81,7 @@ public:
77 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();81 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
78 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();82 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
7983
80 OutputStream &operator+=(StringView R) {84 OutputBuffer &operator+=(StringView R) {
81 size_t Size = R.size();85 size_t Size = R.size();
82 if (Size == 0)86 if (Size == 0)
83 return *this;87 return *this;
...@@ -87,17 +91,28 @@ public:...@@ -87,17 +91,28 @@ public:
87 return *this;91 return *this;
88 }92 }
8993
90 OutputStream &operator+=(char C) {94 OutputBuffer &operator+=(char C) {
91 grow(1);95 grow(1);
92 Buffer[CurrentPosition++] = C;96 Buffer[CurrentPosition++] = C;
93 return *this;97 return *this;
94 }98 }
9599
96 OutputStream &operator<<(StringView R) { return (*this += R); }100 OutputBuffer &operator<<(StringView R) { return (*this += R); }
97101
98 OutputStream &operator<<(char C) { return (*this += C); }102 OutputBuffer prepend(StringView R) {
103 size_t Size = R.size();
104
105 grow(Size);
106 std::memmove(Buffer + Size, Buffer, CurrentPosition);
107 std::memcpy(Buffer, R.begin(), Size);
108 CurrentPosition += Size;
99109
100 OutputStream &operator<<(long long N) {110 return *this;
111 }
112
113 OutputBuffer &operator<<(char C) { return (*this += C); }
114
115 OutputBuffer &operator<<(long long N) {
101 if (N < 0)116 if (N < 0)
102 writeUnsigned(static_cast<unsigned long long>(-N), true);117 writeUnsigned(static_cast<unsigned long long>(-N), true);
103 else118 else
...@@ -105,27 +120,37 @@ public:...@@ -105,27 +120,37 @@ public:
105 return *this;120 return *this;
106 }121 }
107122
108 OutputStream &operator<<(unsigned long long N) {123 OutputBuffer &operator<<(unsigned long long N) {
109 writeUnsigned(N, false);124 writeUnsigned(N, false);
110 return *this;125 return *this;
111 }126 }
112127
113 OutputStream &operator<<(long N) {128 OutputBuffer &operator<<(long N) {
114 return this->operator<<(static_cast<long long>(N));129 return this->operator<<(static_cast<long long>(N));
115 }130 }
116131
117 OutputStream &operator<<(unsigned long N) {132 OutputBuffer &operator<<(unsigned long N) {
118 return this->operator<<(static_cast<unsigned long long>(N));133 return this->operator<<(static_cast<unsigned long long>(N));
119 }134 }
120135
121 OutputStream &operator<<(int N) {136 OutputBuffer &operator<<(int N) {
122 return this->operator<<(static_cast<long long>(N));137 return this->operator<<(static_cast<long long>(N));
123 }138 }
124139
125 OutputStream &operator<<(unsigned int N) {140 OutputBuffer &operator<<(unsigned int N) {
126 return this->operator<<(static_cast<unsigned long long>(N));141 return this->operator<<(static_cast<unsigned long long>(N));
127 }142 }
128143
144 void insert(size_t Pos, const char *S, size_t N) {
145 assert(Pos <= CurrentPosition);
146 if (N == 0)
147 return;
148 grow(N);
149 std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
150 std::memcpy(Buffer + Pos, S, N);
151 CurrentPosition += N;
152 }
153
129 size_t getCurrentPosition() const { return CurrentPosition; }154 size_t getCurrentPosition() const { return CurrentPosition; }
130 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }155 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
131156
...@@ -171,7 +196,7 @@ public:...@@ -171,7 +196,7 @@ public:
171 SwapAndRestore &operator=(const SwapAndRestore &) = delete;196 SwapAndRestore &operator=(const SwapAndRestore &) = delete;
172};197};
173198
174inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,199inline bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB,
175 size_t InitSize) {200 size_t InitSize) {
176 size_t BufferSize;201 size_t BufferSize;
177 if (Buf == nullptr) {202 if (Buf == nullptr) {
...@@ -182,7 +207,7 @@ inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,...@@ -182,7 +207,7 @@ inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
182 } else207 } else
183 BufferSize = *N;208 BufferSize = *N;
184209
185 S.reset(Buf, BufferSize);210 OB.reset(Buf, BufferSize);
186 return true;211 return true;
187}212}
188213
lib/libcxxabi/src/fallback_malloc.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------ fallback_malloc.cpp -------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/fallback_malloc.h+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------- fallback_malloc.h --------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/include/atomic_support.h deleted-180
...@@ -1,180 +0,0 @@
1//===----------------------------------------------------------------------===////
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/atomic_support.h. Instead
10// of duplicating the file in libc++abi we should require that the libc++
11// sources are available when building libc++abi.
12
13#ifndef ATOMIC_SUPPORT_H
14#define ATOMIC_SUPPORT_H
15
16#include "__config"
17#include "memory" // for __libcpp_relaxed_load
18
19#if defined(__clang__) && __has_builtin(__atomic_load_n) \
20 && __has_builtin(__atomic_store_n) \
21 && __has_builtin(__atomic_add_fetch) \
22 && __has_builtin(__atomic_exchange_n) \
23 && __has_builtin(__atomic_compare_exchange_n) \
24 && defined(__ATOMIC_RELAXED) \
25 && defined(__ATOMIC_CONSUME) \
26 && defined(__ATOMIC_ACQUIRE) \
27 && defined(__ATOMIC_RELEASE) \
28 && defined(__ATOMIC_ACQ_REL) \
29 && defined(__ATOMIC_SEQ_CST)
30# define _LIBCXXABI_HAS_ATOMIC_BUILTINS
31#elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407
32# define _LIBCXXABI_HAS_ATOMIC_BUILTINS
33#endif
34
35#if !defined(_LIBCXXABI_HAS_ATOMIC_BUILTINS) && !defined(_LIBCXXABI_HAS_NO_THREADS)
36# if defined(_LIBCPP_WARNING)
37 _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported")
38# else
39# warning Building libc++ without __atomic builtins is unsupported
40# endif
41#endif
42
43_LIBCPP_BEGIN_NAMESPACE_STD
44
45namespace {
46
47#if defined(_LIBCXXABI_HAS_ATOMIC_BUILTINS) && !defined(_LIBCXXABI_HAS_NO_THREADS)
48
49enum __libcpp_atomic_order {
50 _AO_Relaxed = __ATOMIC_RELAXED,
51 _AO_Consume = __ATOMIC_CONSUME,
52 _AO_Acquire = __ATOMIC_ACQUIRE,
53 _AO_Release = __ATOMIC_RELEASE,
54 _AO_Acq_Rel = __ATOMIC_ACQ_REL,
55 _AO_Seq = __ATOMIC_SEQ_CST
56};
57
58template <class _ValueType, class _FromType>
59inline _LIBCPP_INLINE_VISIBILITY
60void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
61 int __order = _AO_Seq)
62{
63 __atomic_store_n(__dest, __val, __order);
64}
65
66template <class _ValueType, class _FromType>
67inline _LIBCPP_INLINE_VISIBILITY
68void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
69{
70 __atomic_store_n(__dest, __val, _AO_Relaxed);
71}
72
73template <class _ValueType>
74inline _LIBCPP_INLINE_VISIBILITY
75_ValueType __libcpp_atomic_load(_ValueType const* __val,
76 int __order = _AO_Seq)
77{
78 return __atomic_load_n(__val, __order);
79}
80
81template <class _ValueType, class _AddType>
82inline _LIBCPP_INLINE_VISIBILITY
83_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
84 int __order = _AO_Seq)
85{
86 return __atomic_add_fetch(__val, __a, __order);
87}
88
89template <class _ValueType>
90inline _LIBCPP_INLINE_VISIBILITY
91_ValueType __libcpp_atomic_exchange(_ValueType* __target,
92 _ValueType __value, int __order = _AO_Seq)
93{
94 return __atomic_exchange_n(__target, __value, __order);
95}
96
97template <class _ValueType>
98inline _LIBCPP_INLINE_VISIBILITY
99bool __libcpp_atomic_compare_exchange(_ValueType* __val,
100 _ValueType* __expected, _ValueType __after,
101 int __success_order = _AO_Seq,
102 int __fail_order = _AO_Seq)
103{
104 return __atomic_compare_exchange_n(__val, __expected, __after, true,
105 __success_order, __fail_order);
106}
107
108#else // _LIBCPP_HAS_NO_THREADS
109
110enum __libcpp_atomic_order {
111 _AO_Relaxed,
112 _AO_Consume,
113 _AO_Acquire,
114 _AO_Release,
115 _AO_Acq_Rel,
116 _AO_Seq
117};
118
119template <class _ValueType, class _FromType>
120inline _LIBCPP_INLINE_VISIBILITY
121void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
122 int = 0)
123{
124 *__dest = __val;
125}
126
127template <class _ValueType, class _FromType>
128inline _LIBCPP_INLINE_VISIBILITY
129void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
130{
131 *__dest = __val;
132}
133
134template <class _ValueType>
135inline _LIBCPP_INLINE_VISIBILITY
136_ValueType __libcpp_atomic_load(_ValueType const* __val,
137 int = 0)
138{
139 return *__val;
140}
141
142template <class _ValueType, class _AddType>
143inline _LIBCPP_INLINE_VISIBILITY
144_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
145 int = 0)
146{
147 return *__val += __a;
148}
149
150template <class _ValueType>
151inline _LIBCPP_INLINE_VISIBILITY
152_ValueType __libcpp_atomic_exchange(_ValueType* __target,
153 _ValueType __value, int = _AO_Seq)
154{
155 _ValueType old = *__target;
156 *__target = __value;
157 return old;
158}
159
160template <class _ValueType>
161inline _LIBCPP_INLINE_VISIBILITY
162bool __libcpp_atomic_compare_exchange(_ValueType* __val,
163 _ValueType* __expected, _ValueType __after,
164 int = 0, int = 0)
165{
166 if (*__val == *__expected) {
167 *__val = __after;
168 return true;
169 }
170 *__expected = *__val;
171 return false;
172}
173
174#endif // _LIBCPP_HAS_NO_THREADS
175
176} // end namespace
177
178_LIBCPP_END_NAMESPACE_STD
179
180#endif // ATOMIC_SUPPORT_H
lib/libcxxabi/src/private_typeinfo.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===----------------------- private_typeinfo.cpp -------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/private_typeinfo.h+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------ private_typeinfo.h --------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/stdlib_exception.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===---------------------------- exception.cpp ---------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/stdlib_new_delete.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===--------------------- stdlib_new_delete.cpp --------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
lib/libcxxabi/src/stdlib_stdexcept.cpp+2-4
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===------------------------ stdexcept.cpp -------------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.
...@@ -12,9 +12,7 @@...@@ -12,9 +12,7 @@
12#include <cstring>12#include <cstring>
13#include <cstdint>13#include <cstdint>
14#include <cstddef>14#include <cstddef>
1515#include "include/refstring.h" // from libc++
16// This includes an implementation file from libc++.
17#include "../../libcxx/src/include/refstring.h"
1816
19static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), "");17static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), "");
2018
lib/libcxxabi/src/stdlib_typeinfo.cpp+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1//===----------------------------- typeinfo.cpp ---------------------------===//1//===----------------------------------------------------------------------===//
2//2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.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.4// See https://llvm.org/LICENSE.txt for license information.