diff --git a/libcxx/include/__config b/libcxx/include/__config index 5f62b974170f..c97cbae96fba 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -36,7 +36,7 @@ #ifdef __cplusplus -# define _LIBCPP_VERSION 15006 +# define _LIBCPP_VERSION 15007 # define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y # define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y) diff --git a/libcxx/include/__support/musl/xlocale.h b/libcxx/include/__support/musl/xlocale.h index f564c87885ac..e674a41fa622 100644 --- a/libcxx/include/__support/musl/xlocale.h +++ b/libcxx/include/__support/musl/xlocale.h @@ -39,7 +39,7 @@ wcstoll_l(const wchar_t *__nptr, wchar_t **__endptr, int __base, locale_t) { return ::wcstoll(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI long long +inline _LIBCPP_HIDE_FROM_ABI unsigned long long wcstoull_l(const wchar_t *__nptr, wchar_t **__endptr, int __base, locale_t) { return ::wcstoull(__nptr, __endptr, __base); } diff --git a/libcxx/include/vector b/libcxx/include/vector index 252a0f051ff5..63759407ce94 100644 --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -297,6 +297,7 @@ erase_if(vector& c, Predicate pred); // C++20 #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/swap.h> +#include <__utility/transaction.h> #include #include #include @@ -425,18 +426,27 @@ public: value_type, typename iterator_traits<_ForwardIterator>::reference>::value>::type* = 0); - _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY - ~vector() - { - __annotate_delete(); - std::__debug_db_erase_c(this); +private: + class __destroy_vector { + public: + _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {} - if (this->__begin_ != nullptr) - { - __clear(); - __alloc_traits::deallocate(__alloc(), this->__begin_, capacity()); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI void operator()() { + __vec_.__annotate_delete(); + std::__debug_db_erase_c(std::addressof(__vec_)); + + if (__vec_.__begin_ != nullptr) { + __vec_.__clear(); + __alloc_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.capacity()); + } } - } + + private: + vector& __vec_; + }; + +public: + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector(*this)(); } _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __x); _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __x, const __type_identity_t& __a); @@ -1075,12 +1085,14 @@ template _LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(size_type __n) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n); } + __guard.__complete(); } #if _LIBCPP_STD_VER > 11 @@ -1089,12 +1101,14 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) : __end_cap_(nullptr, __a) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n); } + __guard.__complete(); } #endif @@ -1102,12 +1116,14 @@ template _LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n, __x); } + __guard.__complete(); } template @@ -1120,9 +1136,11 @@ vector<_Tp, _Allocator>::vector(_InputIterator __first, typename iterator_traits<_InputIterator>::reference>::value, _InputIterator>::type __last) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); for (; __first != __last; ++__first) emplace_back(*__first); + __guard.__complete(); } template @@ -1135,9 +1153,11 @@ vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, c typename iterator_traits<_InputIterator>::reference>::value>::type*) : __end_cap_(nullptr, __a) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); for (; __first != __last; ++__first) emplace_back(*__first); + __guard.__complete(); } template @@ -1150,13 +1170,15 @@ vector<_Tp, _Allocator>::vector(_ForwardIterator __first, typename iterator_traits<_ForwardIterator>::reference>::value, _ForwardIterator>::type __last) { - _VSTD::__debug_db_insert_c(this); - size_type __n = static_cast(_VSTD::distance(__first, __last)); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); + size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last, __n); } + __guard.__complete(); } template @@ -1169,13 +1191,15 @@ vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __las typename iterator_traits<_ForwardIterator>::reference>::value>::type*) : __end_cap_(nullptr, __a) { - _VSTD::__debug_db_insert_c(this); - size_type __n = static_cast(_VSTD::distance(__first, __last)); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); + size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last, __n); } + __guard.__complete(); } template @@ -1183,13 +1207,15 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(const vector& __x) : __end_cap_(nullptr, __alloc_traits::select_on_container_copy_construction(__x.__alloc())) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); size_type __n = __x.size(); if (__n > 0) { __vallocate(__n); __construct_at_end(__x.__begin_, __x.__end_, __n); } + __guard.__complete(); } template @@ -1197,13 +1223,15 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t& __a) : __end_cap_(nullptr, __a) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); size_type __n = __x.size(); if (__n > 0) { __vallocate(__n); __construct_at_end(__x.__begin_, __x.__end_, __n); } + __guard.__complete(); } template @@ -1243,7 +1271,9 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t _Ip; + auto __guard = std::__make_transaction(__destroy_vector(*this)); assign(_Ip(__x.begin()), _Ip(__x.end())); + __guard.__complete(); } } @@ -1254,12 +1284,14 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>::vector(initializer_list __il) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); if (__il.size() > 0) { __vallocate(__il.size()); __construct_at_end(__il.begin(), __il.end(), __il.size()); } + __guard.__complete(); } template @@ -1268,12 +1300,14 @@ inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>::vector(initializer_list __il, const allocator_type& __a) : __end_cap_(nullptr, __a) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); if (__il.size() > 0) { __vallocate(__il.size()); __construct_at_end(__il.begin(), __il.end(), __il.size()); } + __guard.__complete(); } #endif // _LIBCPP_CXX03_LANG @@ -2111,8 +2145,26 @@ public: #else _NOEXCEPT; #endif - _LIBCPP_CONSTEXPR_AFTER_CXX17 ~vector(); - _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n); + +private: + class __destroy_vector { + public: + _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {} + + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI void operator()() { + if (__vec_.__begin_ != nullptr) + __storage_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.__cap()); + std::__debug_db_invalidate_all(this); + } + + private: + vector& __vec_; + }; + +public: + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 ~vector() { __destroy_vector(*this)(); } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n); #if _LIBCPP_STD_VER > 11 _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n, const allocator_type& __a); #endif @@ -2647,12 +2699,14 @@ vector::vector(_ForwardIterator __first, _ForwardIterator __la __size_(0), __cap_alloc_(0, __default_init_tag()) { - size_type __n = static_cast(_VSTD::distance(__first, __last)); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last); } + __guard.__complete(); } template @@ -2664,12 +2718,14 @@ vector::vector(_ForwardIterator __first, _ForwardIterator __la __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { - size_type __n = static_cast(_VSTD::distance(__first, __last)); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last); } + __guard.__complete(); } #ifndef _LIBCPP_CXX03_LANG @@ -2706,15 +2762,6 @@ vector::vector(initializer_list __il, const alloca #endif // _LIBCPP_CXX03_LANG -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 -vector::~vector() -{ - if (__begin_ != nullptr) - __storage_traits::deallocate(__alloc(), __begin_, __cap()); - std::__debug_db_invalidate_all(this); -} - template _LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(const vector& __v) diff --git a/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp new file mode 100644 index 000000000000..592d733de42d --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp @@ -0,0 +1,141 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-exceptions + +// (bug report: https://llvm.org/PR58392) +// Check that vector constructors don't leak memory when an operation inside the constructor throws an exception + +#include +#include + +#include "count_new.h" +#include "test_iterators.h" + +template +struct Allocator { + using value_type = T; + using is_always_equal = std::false_type; + + template + Allocator(const Allocator&) {} + + Allocator(bool should_throw = true) { + if (should_throw) + throw 0; + } + + T* allocate(int n) { return std::allocator().allocate(n); } + void deallocate(T* ptr, int n) { std::allocator().deallocate(ptr, n); } + + friend bool operator==(const Allocator&, const Allocator&) { return false; } +}; + +template +struct Iterator { + using iterator_category = IterCat; + using difference_type = std::ptrdiff_t; + using value_type = bool; + using reference = bool&; + using pointer = bool*; + + int i_; + bool b_ = true; + Iterator(int i = 0) : i_(i) {} + bool& operator*() { + if (i_ == 1) + throw 1; + return b_; + } + + friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ == rhs.i_; } + + friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ != rhs.i_; } + + Iterator& operator++() { + ++i_; + return *this; + } + + Iterator operator++(int) { + auto tmp = *this; + ++i_; + return tmp; + } +}; + +void check_new_delete_called() { + assert(globalMemCounter.new_called == globalMemCounter.delete_called); + assert(globalMemCounter.new_array_called == globalMemCounter.delete_array_called); + assert(globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called); + assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called); +} + +int main(int, char**) { + using AllocVec = std::vector >; + +#if TEST_STD_VER >= 14 + try { // Throw in vector(size_type, const allocator_type&) from allocator + Allocator alloc(false); + AllocVec get_alloc(0, alloc); + } catch (int) { + } + check_new_delete_called(); +#endif // TEST_STD_VER >= 14 + + try { // Throw in vector(InputIterator, InputIterator) from input iterator + std::vector vec((Iterator()), Iterator(2)); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator) from forward iterator + std::vector vec((Iterator()), Iterator(2)); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator) from allocator + int a[] = {1, 2}; + AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2)); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator + std::allocator alloc; + std::vector vec(Iterator(), Iterator(2), alloc); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator + std::allocator alloc; + std::vector vec(Iterator(), Iterator(2), alloc); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator + bool a[] = {true, false}; + Allocator alloc(false); + AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2), alloc); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator + bool a[] = {true, false}; + Allocator alloc(false); + AllocVec vec(forward_iterator(a), forward_iterator(a + 2), alloc); + } catch (int) { + } + check_new_delete_called(); + + return 0; +} diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp new file mode 100644 index 000000000000..26ad7b4fd05a --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp @@ -0,0 +1,229 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-exceptions + +// (bug report: https://llvm.org/PR58392) +// Check that vector constructors don't leak memory when an operation inside the constructor throws an exception + +#include +#include + +#include "count_new.h" +#include "test_iterators.h" + +template +struct Allocator { + using value_type = T; + using is_always_equal = std::false_type; + + Allocator(bool should_throw = true) { + if (should_throw) + throw 0; + } + + T* allocate(int n) { return std::allocator().allocate(n); } + void deallocate(T* ptr, int n) { std::allocator().deallocate(ptr, n); } + + friend bool operator==(const Allocator&, const Allocator&) { return false; } +}; + +struct ThrowingT { + int* throw_after_n_ = nullptr; + ThrowingT() { throw 0; } + + ThrowingT(int& throw_after_n) : throw_after_n_(&throw_after_n) { + if (throw_after_n == 0) + throw 0; + --throw_after_n; + } + + ThrowingT(const ThrowingT&) { + if (throw_after_n_ == nullptr || *throw_after_n_ == 0) + throw 1; + --*throw_after_n_; + } + + ThrowingT& operator=(const ThrowingT&) { + if (throw_after_n_ == nullptr || *throw_after_n_ == 0) + throw 1; + --*throw_after_n_; + return *this; + } +}; + +template +struct Iterator { + using iterator_category = IterCat; + using difference_type = std::ptrdiff_t; + using value_type = int; + using reference = int&; + using pointer = int*; + + int i_; + Iterator(int i = 0) : i_(i) {} + int& operator*() { + if (i_ == 1) + throw 1; + return i_; + } + + friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ == rhs.i_; } + + friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ != rhs.i_; } + + Iterator& operator++() { + ++i_; + return *this; + } + + Iterator operator++(int) { + auto tmp = *this; + ++i_; + return tmp; + } +}; + +void check_new_delete_called() { + assert(globalMemCounter.new_called == globalMemCounter.delete_called); + assert(globalMemCounter.new_array_called == globalMemCounter.delete_array_called); + assert(globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called); + assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called); +} + +int main(int, char**) { + using AllocVec = std::vector >; + try { // vector() + AllocVec vec; + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(size_type) from type + std::vector get_alloc(1); + } catch (int) { + } + check_new_delete_called(); + +#if TEST_STD_VER >= 14 + try { // Throw in vector(size_type, value_type) from type + int throw_after = 1; + ThrowingT v(throw_after); + std::vector get_alloc(1, v); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(size_type, const allocator_type&) from allocator + Allocator alloc(false); + AllocVec get_alloc(0, alloc); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(size_type, const allocator_type&) from the type + std::vector vec(1, std::allocator()); + } catch (int) { + } + check_new_delete_called(); +#endif // TEST_STD_VER >= 14 + + try { // Throw in vector(InputIterator, InputIterator) from input iterator + std::vector vec((Iterator()), Iterator(2)); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator) from forward iterator + std::vector vec((Iterator()), Iterator(2)); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator) from allocator + int a[] = {1, 2}; + AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2)); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator + std::allocator alloc; + std::vector vec(Iterator(), Iterator(2), alloc); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator + std::allocator alloc; + std::vector vec(Iterator(), Iterator(2), alloc); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator + int a[] = {1, 2}; + Allocator alloc(false); + AllocVec vec(cpp17_input_iterator(a), cpp17_input_iterator(a + 2), alloc); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator + int a[] = {1, 2}; + Allocator alloc(false); + AllocVec vec(forward_iterator(a), forward_iterator(a + 2), alloc); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(const vector&) from type + std::vector vec; + int throw_after = 0; + vec.emplace_back(throw_after); + auto vec2 = vec; + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(const vector&, const allocator_type&) from type + std::vector vec; + int throw_after = 1; + vec.emplace_back(throw_after); + std::vector vec2(vec, std::allocator()); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(vector&&, const allocator_type&) from type + std::vector > vec(Allocator(false)); + int throw_after = 1; + vec.emplace_back(throw_after); + std::vector > vec2(std::move(vec), Allocator(false)); + } catch (int) { + } + check_new_delete_called(); + +#if TEST_STD_VER >= 11 + try { // Throw in vector(initializer_list) from type + int throw_after = 1; + std::vector vec({ThrowingT(throw_after)}); + } catch (int) { + } + check_new_delete_called(); + + try { // Throw in vector(initializer_list, const allocator_type&) constructor from type + int throw_after = 1; + std::vector vec({ThrowingT(throw_after)}, std::allocator()); + } catch (int) { + } + check_new_delete_called(); +#endif // TEST_STD_VER >= 11 + + return 0; +} diff --git a/lld/test/wasm/export-all.s b/lld/test/wasm/export-all.s index 009da9f6a381..5af835ce485e 100644 --- a/lld/test/wasm/export-all.s +++ b/lld/test/wasm/export-all.s @@ -40,9 +40,12 @@ foo: # CHECK-NEXT: - Name: __heap_base # CHECK-NEXT: Kind: GLOBAL # CHECK-NEXT: Index: 4 -# CHECK-NEXT: - Name: __memory_base +# CHECK-NEXT: - Name: __heap_end # CHECK-NEXT: Kind: GLOBAL # CHECK-NEXT: Index: 5 -# CHECK-NEXT: - Name: __table_base +# CHECK-NEXT: - Name: __memory_base # CHECK-NEXT: Kind: GLOBAL # CHECK-NEXT: Index: 6 +# CHECK-NEXT: - Name: __table_base +# CHECK-NEXT: Kind: GLOBAL +# CHECK-NEXT: Index: 7 diff --git a/lld/test/wasm/mutable-global-exports.s b/lld/test/wasm/mutable-global-exports.s index e2e45ff93a4b..98009610ac55 100644 --- a/lld/test/wasm/mutable-global-exports.s +++ b/lld/test/wasm/mutable-global-exports.s @@ -79,10 +79,13 @@ _start: # CHECK-ALL-NEXT: - Name: __heap_base # CHECK-ALL-NEXT: Kind: GLOBAL # CHECK-ALL-NEXT: Index: 5 -# CHECK-ALL-NEXT: - Name: __memory_base +# CHECK-ALL-NEXT: - Name: __heap_end # CHECK-ALL-NEXT: Kind: GLOBAL # CHECK-ALL-NEXT: Index: 6 -# CHECK-ALL-NEXT: - Name: __table_base +# CHECK-ALL-NEXT: - Name: __memory_base # CHECK-ALL-NEXT: Kind: GLOBAL # CHECK-ALL-NEXT: Index: 7 +# CHECK-ALL-NEXT: - Name: __table_base +# CHECK-ALL-NEXT: Kind: GLOBAL +# CHECK-ALL-NEXT: Index: 8 # CHECK-ALL-NEXT: - Type: CODE diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index 0a0f0c8a05bd..4afbfe24110f 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -681,6 +681,7 @@ static void createOptionalSymbols() { if (!config->isPic) { WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base"); WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base"); + WasmSym::heapEnd = symtab->addOptionalDataSymbol("__heap_end"); WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base"); WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base"); if (config->is64.value_or(false)) diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp index e0670cea6425..a79c5bec3b3b 100644 --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -83,6 +83,7 @@ DefinedData *WasmSym::dsoHandle; DefinedData *WasmSym::dataEnd; DefinedData *WasmSym::globalBase; DefinedData *WasmSym::heapBase; +DefinedData *WasmSym::heapEnd; DefinedData *WasmSym::initMemoryFlag; GlobalSymbol *WasmSym::stackPointer; GlobalSymbol *WasmSym::tlsBase; diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h index c17b720a90fa..32e75a69c5f8 100644 --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -538,11 +538,14 @@ struct WasmSym { // Symbol marking the end of the data and bss. static DefinedData *dataEnd; - // __heap_base - // Symbol marking the end of the data, bss and explicit stack. Any linear - // memory following this address is not used by the linked code and can - // therefore be used as a backing store for brk()/malloc() implementations. + // __heap_base/__heap_end + // Symbols marking the beginning and end of the "heap". It starts at the end + // of the data, bss and explicit stack, and extends to the end of the linear + // memory allocated by wasm-ld. This region of memory is not used by the + // linked code, so it may be used as a backing store for `sbrk` or `malloc` + // implementations. static DefinedData *heapBase; + static DefinedData *heapEnd; // __wasm_init_memory_flag // Symbol whose contents are nonzero iff memory has already been initialized. diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index f98c95526c9e..f6bbaa02b571 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -340,10 +340,20 @@ void Writer::layoutMemory() { Twine(maxMemorySetting)); memoryPtr = config->initialMemory; } - out.memorySec->numMemoryPages = - alignTo(memoryPtr, WasmPageSize) / WasmPageSize; + + memoryPtr = alignTo(memoryPtr, WasmPageSize); + + out.memorySec->numMemoryPages = memoryPtr / WasmPageSize; log("mem: total pages = " + Twine(out.memorySec->numMemoryPages)); + if (WasmSym::heapEnd) { + // Set `__heap_end` to follow the end of the statically allocated linear + // memory. The fact that this comes last means that a malloc/brk + // implementation can grow the heap at runtime. + log("mem: heap end = " + Twine(memoryPtr)); + WasmSym::heapEnd->setVA(memoryPtr); + } + if (config->maxMemory != 0) { if (config->maxMemory != alignTo(config->maxMemory, WasmPageSize)) error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned"); @@ -363,7 +373,7 @@ void Writer::layoutMemory() { if (config->isPic) max = maxMemorySetting; else - max = alignTo(memoryPtr, WasmPageSize); + max = memoryPtr; } out.memorySec->maxMemoryPages = max / WasmPageSize; log("mem: max pages = " + Twine(out.memorySec->maxMemoryPages)); diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 28e28cfe7b6a..db207e3328be 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -22,7 +22,7 @@ if(NOT DEFINED LLVM_VERSION_MINOR) set(LLVM_VERSION_MINOR 0) endif() if(NOT DEFINED LLVM_VERSION_PATCH) - set(LLVM_VERSION_PATCH 6) + set(LLVM_VERSION_PATCH 7) endif() if(NOT DEFINED LLVM_VERSION_SUFFIX) set(LLVM_VERSION_SUFFIX) diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index 85d051cfdbe7..a8d40edd88d3 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -1237,7 +1237,13 @@ void PEI::insertZeroCallUsedRegs(MachineFunction &MF) { if (!MO.isReg()) continue; - for (MCPhysReg SReg : TRI.sub_and_superregs_inclusive(MO.getReg())) + MCRegister Reg = MO.getReg(); + + // This picks up sibling registers (e.q. %al -> %ah). + for (MCRegUnitIterator Unit(Reg, &TRI); Unit.isValid(); ++Unit) + RegsToZero.reset(*Unit); + + for (MCPhysReg SReg : TRI.sub_and_superregs_inclusive(Reg)) RegsToZero.reset(SReg); } } diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index 9e4e26f1392e..cb552f212fbb 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -443,6 +443,9 @@ void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg, SpilledOperandsMap[MO->getParent()].push_back(MO); for (auto MISpilledOperands : SpilledOperandsMap) { MachineInstr &DBG = *MISpilledOperands.first; + // We don't have enough support for tracking operands of DBG_VALUE_LISTs. + if (DBG.isDebugValueList()) + continue; MachineInstr *NewDV = buildDbgValueForSpill( *MBB, Before, *MISpilledOperands.first, FI, MISpilledOperands.second); assert(NewDV->getParent() == MBB && "dangling parent pointer"); diff --git a/llvm/test/CodeGen/PowerPC/regalloc-fast-debug-spill.ll b/llvm/test/CodeGen/PowerPC/regalloc-fast-debug-spill.ll new file mode 100644 index 000000000000..cae3cb3bbdf8 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/regalloc-fast-debug-spill.ll @@ -0,0 +1,250 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -O0 < %s | FileCheck %s + +; This test would previously crash in RegisterScavenging, or with assertions +; enabled it would fail when RegAllocFast calls clearVirtRegs. This was due to +; unhandled virt regs in cloned DBG_VALUE_LIST for spills, which are now skipped. +; https://github.com/llvm/llvm-project/issues/59172 + +target datalayout = "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512" +target triple = "powerpc64le-unknown-linux-gnu" + +; Function Attrs: argmemonly nocallback nofree nounwind willreturn +declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #0 + +; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +define void @read_to_end(i1 %0) personality ptr null { +; CHECK-LABEL: read_to_end: +; CHECK: # %bb.0: +; CHECK-NEXT: mflr 0 +; CHECK-NEXT: std 0, 16(1) +; CHECK-NEXT: stdu 1, -80(1) +; CHECK-NEXT: .cfi_def_cfa_offset 80 +; CHECK-NEXT: .cfi_offset lr, 16 +; CHECK-NEXT: andi. 3, 3, 1 +; CHECK-NEXT: mfocrf 3, 128 +; CHECK-NEXT: rlwinm 3, 3, 1, 0, 0 +; CHECK-NEXT: stw 3, 60(1) +; CHECK-NEXT: ld 3, 0(0) +; CHECK-NEXT: std 3, 64(1) # 8-byte Folded Spill +; CHECK-NEXT: li 3, 0 +; CHECK-NEXT: std 3, 72(1) # 8-byte Folded Spill +; CHECK-NEXT: #DEBUG_VALUE: spec_extend:iterator <- [DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_constu 1, DW_OP_mul, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment 64 64] undef, $x3 +; CHECK-NEXT: creqv 20, 20, 20 +; CHECK-NEXT: crxor 20, 1, 20 +; CHECK-NEXT: bc 12, 20, .LBB0_2 +; CHECK-NEXT: b .LBB0_1 +; CHECK-NEXT: .LBB0_1: +; CHECK-NEXT: addi 1, 1, 80 +; CHECK-NEXT: ld 0, 16(1) +; CHECK-NEXT: mtlr 0 +; CHECK-NEXT: blr +; CHECK-NEXT: .LBB0_2: +; CHECK-NEXT: ld 5, 72(1) # 8-byte Folded Reload +; CHECK-NEXT: ld 4, 64(1) # 8-byte Folded Reload +; CHECK-NEXT: li 3, 0 +; CHECK-NEXT: bl memcpy +; CHECK-NEXT: nop +; CHECK-NEXT: lwz 4, 60(1) +; CHECK-NEXT: # implicit-def: $cr5lt +; CHECK-NEXT: mfocrf 3, 4 +; CHECK-NEXT: rlwimi 3, 4, 12, 20, 20 +; CHECK-NEXT: mtocrf 4, 3 +; CHECK-NEXT: bc 12, 20, .LBB0_4 +; CHECK-NEXT: b .LBB0_3 +; CHECK-NEXT: .LBB0_3: +; CHECK-NEXT: b .LBB0_4 +; CHECK-NEXT: .LBB0_4: +; CHECK-NEXT: addi 1, 1, 80 +; CHECK-NEXT: ld 0, 16(1) +; CHECK-NEXT: mtlr 0 +; CHECK-NEXT: blr + %2 = load ptr, ptr null, align 8 + %3 = sub i64 0, 0 + call void @llvm.dbg.value(metadata !DIArgList(ptr %2, i64 %3), metadata !129, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 1, DW_OP_mul, DW_OP_plus, DW_OP_stack_value, DW_OP_LLVM_fragment, 64, 64)), !dbg !140 + br i1 %0, label %4, label %5 + +4: ; preds = %1 + ret void + +5: ; preds = %1 + tail call void @llvm.memcpy.p0.p0.i64(ptr null, ptr %2, i64 %3, i1 false) + br i1 %0, label %7, label %6 + +6: ; preds = %5 + br label %7 + +7: ; preds = %6, %5 + ret void +} + +attributes #0 = { argmemonly nocallback nofree nounwind willreturn } +attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } + +!llvm.module.flags = !{!0} +!llvm.dbg.cu = !{!1} + +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !2, producer: "clang LLVM (rustc version 1.67.0-dev)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4) +!2 = !DIFile(filename: "library/std/src/lib.rs/@/std.ff910444-cgu.11", directory: "/home/jistone/rust") +!3 = !{} +!4 = !{!5, !12, !18, !23, !28, !34, !43, !49, !52, !58, !64, !68, !77, !81, !86, !90, !98, !102, !106, !111, !117, !124} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !8, isLocal: true, isDefinition: true) +!7 = !DIFile(filename: "", directory: "") +!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 384, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !9, templateParams: !3, identifier: "1ec913b2a90798f33a12cdc627a17d3d") +!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "String", scope: !10, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "b616ccc9e18737e903266aae12eea82") +!10 = !DINamespace(name: "string", scope: !11) +!11 = !DINamespace(name: "alloc", scope: null) +!12 = !DIGlobalVariableExpression(var: !13, expr: !DIExpression()) +!13 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !14, isLocal: true, isDefinition: true) +!14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !15, templateParams: !3, identifier: "7f09904511177108b2e94c43effbe403") +!15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "BorrowMutError", scope: !16, file: !7, align: 8, elements: !3, identifier: "acf9edd4524e0ff9a9398905d3ba31a6") +!16 = !DINamespace(name: "cell", scope: !17) +!17 = !DINamespace(name: "core", scope: null) +!18 = !DIGlobalVariableExpression(var: !19, expr: !DIExpression()) +!19 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !20, isLocal: true, isDefinition: true) +!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !21, templateParams: !3, identifier: "84cb7e6d80fc4c532d8f45aaa75a7ae3") +!21 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Error", scope: !22, file: !7, align: 8, elements: !3, identifier: "abcb9fb1fe4fda8598a8687b517935b") +!22 = !DINamespace(name: "fmt", scope: !17) +!23 = !DIGlobalVariableExpression(var: !24, expr: !DIExpression()) +!24 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !25, isLocal: true, isDefinition: true) +!25 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !26, templateParams: !3, identifier: "bafa31943f8233dbf8d2de6a615f899") +!26 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TryFromSliceError", scope: !27, file: !7, align: 8, elements: !3, templateParams: !3, identifier: "2dd7cf8d77337f63be7c7f5feb370b37") +!27 = !DINamespace(name: "array", scope: !17) +!28 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression()) +!29 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !30, isLocal: true, isDefinition: true) +!30 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !31, templateParams: !3, identifier: "3292395ea0f5a7e3e88f36db52eb440c") +!31 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TryFromIntError", scope: !32, file: !7, align: 8, elements: !3, templateParams: !3, identifier: "5b131d57d001578fbf4fb83f2028eb12") +!32 = !DINamespace(name: "error", scope: !33) +!33 = !DINamespace(name: "num", scope: !17) +!34 = !DIGlobalVariableExpression(var: !35, expr: !DIExpression()) +!35 = distinct !DIGlobalVariable(name: "OUTPUT_CAPTURE_USED", linkageName: "_ZN3std2io5stdio19OUTPUT_CAPTURE_USED17h6bb564f9f9e20f1bE", scope: !36, file: !39, line: 38, type: !40, isLocal: true, isDefinition: true, align: 8) +!36 = !DINamespace(name: "stdio", scope: !37) +!37 = !DINamespace(name: "io", scope: !38) +!38 = !DINamespace(name: "std", scope: null) +!39 = !DIFile(filename: "library/std/src/io/stdio.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "6e6a519ce8370e29f07d850a34a413c1") +!40 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "AtomicBool", scope: !41, file: !7, size: 8, align: 8, elements: !3, templateParams: !3, identifier: "c1cddf0305d4e6a98a8ddd4b6fdb5b91") +!41 = !DINamespace(name: "atomic", scope: !42) +!42 = !DINamespace(name: "sync", scope: !17) +!43 = !DIGlobalVariableExpression(var: !44, expr: !DIExpression()) +!44 = distinct !DIGlobalVariable(name: "INSTANCE", linkageName: "_ZN3std2io5stdio5stdin8INSTANCE17h225ddf7c6608f4aaE", scope: !45, file: !39, line: 320, type: !46, isLocal: true, isDefinition: true, align: 64) +!45 = !DINamespace(name: "stdin", scope: !36) +!46 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "OnceLock>>", scope: !47, file: !7, size: 448, align: 64, elements: !3, templateParams: !3, identifier: "2236c08b0846b8b2f33c235183822718") +!47 = !DINamespace(name: "once_lock", scope: !48) +!48 = !DINamespace(name: "sync", scope: !38) +!49 = !DIGlobalVariableExpression(var: !50, expr: !DIExpression()) +!50 = distinct !DIGlobalVariable(name: "STDOUT", linkageName: "_ZN3std2io5stdio6STDOUT17hd8472b9eb112f94aE", scope: !36, file: !39, line: 554, type: !51, isLocal: true, isDefinition: true, align: 64) +!51 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "OnceLock>>>", scope: !47, file: !7, size: 512, align: 64, elements: !3, templateParams: !3, identifier: "31535135376bcf9dc80438cb0beaa95") +!52 = !DIGlobalVariableExpression(var: !53, expr: !DIExpression()) +!53 = distinct !DIGlobalVariable(name: "INSTANCE", linkageName: "_ZN3std2io5stdio6stderr8INSTANCE17he81b75fda1609dccE", scope: !54, file: !39, line: 844, type: !55, isLocal: true, isDefinition: true, align: 64) +!54 = !DINamespace(name: "stderr", scope: !36) +!55 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "ReentrantMutex>", scope: !56, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "5c48123cbde8afbfd832b70e8bb014b") +!56 = !DINamespace(name: "remutex", scope: !57) +!57 = !DINamespace(name: "sys_common", scope: !38) +!58 = !DIGlobalVariableExpression(var: !59, expr: !DIExpression()) +!59 = distinct !DIGlobalVariable(name: " as core::fmt::Write>::{vtable}", scope: null, file: !7, type: !60, isLocal: true, isDefinition: true) +!60 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: " as core::fmt::Write>::{vtable_type}", file: !7, size: 384, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !61, templateParams: !3, identifier: "43681bec3eba7b0defb75fd847230ef3") +!61 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Adapter", scope: !62, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "eda3cd8f60f00feb7019a3d90d2413dd") +!62 = !DINamespace(name: "write_fmt", scope: !63) +!63 = !DINamespace(name: "Write", scope: !37) +!64 = !DIGlobalVariableExpression(var: !65, expr: !DIExpression()) +!65 = distinct !DIGlobalVariable(name: " as core::fmt::Write>::{vtable}", scope: null, file: !7, type: !66, isLocal: true, isDefinition: true) +!66 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: " as core::fmt::Write>::{vtable_type}", file: !7, size: 384, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !67, templateParams: !3, identifier: "2235adf22355a080446df25ada963d8f") +!67 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Adapter", scope: !62, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "50f418463bae1beffe989359452b170a") +!68 = !DIGlobalVariableExpression(var: !69, expr: !DIExpression()) +!69 = distinct !DIGlobalVariable(name: "__KEY", linkageName: "_ZN3std2io5stdio14OUTPUT_CAPTURE7__getit5__KEY17h82ea5b0c4e81236dE", scope: !70, file: !72, line: 331, type: !73, isLocal: true, isDefinition: true, align: 64) +!70 = !DINamespace(name: "__getit", scope: !71) +!71 = !DINamespace(name: "OUTPUT_CAPTURE", scope: !36) +!72 = !DIFile(filename: "library/std/src/thread/local.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "e3766fd5751a888dc2040f63031e944e") +!73 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Key>>>>>", scope: !74, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "4d1514f685cbd010d7b86d2eef080b6c") +!74 = !DINamespace(name: "fast", scope: !75) +!75 = !DINamespace(name: "local", scope: !76) +!76 = !DINamespace(name: "thread", scope: !38) +!77 = !DIGlobalVariableExpression(var: !78, expr: !DIExpression()) +!78 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !79, isLocal: true, isDefinition: true) +!79 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !80, templateParams: !3, identifier: "1a7c0806435616633a284f48de1194c5") +!80 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) +!81 = !DIGlobalVariableExpression(var: !82, expr: !DIExpression()) +!82 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !83, isLocal: true, isDefinition: true) +!83 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !84, templateParams: !3, identifier: "8e82e7dafb168f2995a6711175975a8") +!84 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "PathBuf", scope: !85, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "85bd755ad2187534379df2cc01ef53a0") +!85 = !DINamespace(name: "path", scope: !38) +!86 = !DIGlobalVariableExpression(var: !87, expr: !DIExpression()) +!87 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !88, isLocal: true, isDefinition: true) +!88 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !89, templateParams: !3, identifier: "a8f7c32dd1df279746df60c6d46ce35e") +!89 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean) +!90 = !DIGlobalVariableExpression(var: !91, expr: !DIExpression()) +!91 = distinct !DIGlobalVariable(name: "STATX_STATE", linkageName: "_ZN3std3sys4unix2fs9try_statx11STATX_STATE17h465ade0d62262837E", scope: !92, file: !96, line: 157, type: !97, isLocal: true, isDefinition: true, align: 8) +!92 = !DINamespace(name: "try_statx", scope: !93) +!93 = !DINamespace(name: "fs", scope: !94) +!94 = !DINamespace(name: "unix", scope: !95) +!95 = !DINamespace(name: "sys", scope: !38) +!96 = !DIFile(filename: "library/std/src/sys/unix/fs.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "594559328c68ee77afe955cd571273ee") +!97 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "AtomicU8", scope: !41, file: !7, size: 8, align: 8, elements: !3, templateParams: !3, identifier: "dda3b691bea8e1b5292414dd97926af2") +!98 = !DIGlobalVariableExpression(var: !99, expr: !DIExpression()) +!99 = distinct !DIGlobalVariable(name: "<&bool as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !100, isLocal: true, isDefinition: true) +!100 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&bool as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !101, templateParams: !3, identifier: "5e8d2c48c9cc79c318e2bd28b03e141a") +!101 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&bool", baseType: !89, size: 64, align: 64, dwarfAddressSpace: 0) +!102 = !DIGlobalVariableExpression(var: !103, expr: !DIExpression()) +!103 = distinct !DIGlobalVariable(name: "<&i32 as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !104, isLocal: true, isDefinition: true) +!104 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&i32 as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !105, templateParams: !3, identifier: "d4029746615b6a868ffbc67515d99878") +!105 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&i32", baseType: !80, size: 64, align: 64, dwarfAddressSpace: 0) +!106 = !DIGlobalVariableExpression(var: !107, expr: !DIExpression()) +!107 = distinct !DIGlobalVariable(name: "<&u32 as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !108, isLocal: true, isDefinition: true) +!108 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&u32 as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !109, templateParams: !3, identifier: "178e0e76b9d9178d686381b2d05a7777") +!109 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&u32", baseType: !110, size: 64, align: 64, dwarfAddressSpace: 0) +!110 = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned) +!111 = !DIGlobalVariableExpression(var: !112, expr: !DIExpression()) +!112 = distinct !DIGlobalVariable(name: "<&core::option::Option as core::fmt::Debug>::{vtable}", scope: null, file: !7, type: !113, isLocal: true, isDefinition: true) +!113 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&core::option::Option as core::fmt::Debug>::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !114, templateParams: !3, identifier: "7ca8386b4d420d719587fa3255329a7a") +!114 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&core::option::Option", baseType: !115, size: 64, align: 64, dwarfAddressSpace: 0) +!115 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Option", scope: !116, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "ad8474e495013fa1e3af4a6b53a05f4b") +!116 = !DINamespace(name: "option", scope: !17) +!117 = !DIGlobalVariableExpression(var: !118, expr: !DIExpression()) +!118 = distinct !DIGlobalVariable(name: "HAS_CLONE3", linkageName: "_ZN3std3sys4unix7process13process_inner66_$LT$impl$u20$std..sys..unix..process..process_common..Command$GT$7do_fork10HAS_CLONE317h7d23eb353ae1c9a8E", scope: !119, file: !123, line: 148, type: !40, isLocal: true, isDefinition: true, align: 8) +!119 = !DINamespace(name: "do_fork", scope: !120) +!120 = !DINamespace(name: "{impl#0}", scope: !121) +!121 = !DINamespace(name: "process_inner", scope: !122) +!122 = !DINamespace(name: "process", scope: !94) +!123 = !DIFile(filename: "library/std/src/sys/unix/process/process_unix.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "91761d638041a5dd66c0a64d968debe6") +!124 = !DIGlobalVariableExpression(var: !125, expr: !DIExpression()) +!125 = distinct !DIGlobalVariable(name: "::{vtable}", scope: null, file: !7, type: !126, isLocal: true, isDefinition: true) +!126 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", file: !7, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !127, templateParams: !3, identifier: "13903f30d26ee5869ef7a3fc63a2e03d") +!127 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "NonZeroI32", scope: !128, file: !7, size: 32, align: 32, elements: !3, templateParams: !3, identifier: "e292f11a32f1ce5cf3b26864e4a0f5e5") +!128 = !DINamespace(name: "nonzero", scope: !33) +!129 = !DILocalVariable(name: "iterator", arg: 2, scope: !130, file: !131, line: 83, type: !137) +!130 = distinct !DISubprogram(name: "spec_extend", linkageName: "_ZN132_$LT$alloc..vec..Vec$LT$T$C$A$GT$$u20$as$u20$alloc..vec..spec_extend..SpecExtend$LT$$RF$T$C$core..slice..iter..Iter$LT$T$GT$$GT$$GT$11spec_extend17hb56b69f474ec1e6dE", scope: !132, file: !131, line: 83, type: !135, scopeLine: 83, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) +!131 = !DIFile(filename: "library/alloc/src/vec/spec_extend.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "0614d5dabe9e343254af1b3fa1ec7315") +!132 = !DINamespace(name: "{impl#4}", scope: !133) +!133 = !DINamespace(name: "spec_extend", scope: !134) +!134 = !DINamespace(name: "vec", scope: !11) +!135 = distinct !DISubroutineType(types: !136) +!136 = !{null} +!137 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Iter", scope: !138, file: !7, size: 128, align: 64, elements: !3, templateParams: !3, identifier: "c31ab6f02ccece1f1a6e93425acabaa1") +!138 = !DINamespace(name: "iter", scope: !139) +!139 = !DINamespace(name: "slice", scope: !17) +!140 = !DILocation(line: 0, scope: !130, inlinedAt: !141) +!141 = distinct !DILocation(line: 2392, column: 9, scope: !142, inlinedAt: !146) +!142 = distinct !DISubprogram(name: "extend_from_slice", linkageName: "_ZN5alloc3vec16Vec$LT$T$C$A$GT$17extend_from_slice17hbc8d29f2694fd768E", scope: !144, file: !143, line: 2391, type: !145, scopeLine: 2391, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) +!143 = !DIFile(filename: "library/alloc/src/vec/mod.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "0d69d0c0c11b3e47364cf6be0d07c829") +!144 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Vec", scope: !134, file: !7, size: 192, align: 64, elements: !3, templateParams: !3, identifier: "f970dea4d30c1daf847db520fef9390d") +!145 = distinct !DISubroutineType(types: !136) +!146 = distinct !DILocation(line: 330, column: 9, scope: !147, inlinedAt: !154) +!147 = distinct !DILexicalBlock(scope: !149, file: !148, line: 329, column: 9) +!148 = !DIFile(filename: "library/std/src/io/buffered/bufreader.rs", directory: "/home/jistone/rust", checksumkind: CSK_MD5, checksum: "5375e06de487f85ee2f6d21c8a84ce7d") +!149 = distinct !DISubprogram(name: "read_to_end", linkageName: "_ZN82_$LT$std..io..buffered..bufreader..BufReader$LT$R$GT$$u20$as$u20$std..io..Read$GT$11read_to_end17h9f09720ee76e6db9E", scope: !150, file: !148, line: 328, type: !153, scopeLine: 328, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) +!150 = !DINamespace(name: "{impl#3}", scope: !151) +!151 = !DINamespace(name: "bufreader", scope: !152) +!152 = !DINamespace(name: "buffered", scope: !37) +!153 = distinct !DISubroutineType(types: !3) +!154 = distinct !DILocation(line: 464, column: 9, scope: !155, inlinedAt: !158) +!155 = distinct !DISubprogram(name: "read_to_end", linkageName: "_ZN59_$LT$std..io..stdio..StdinLock$u20$as$u20$std..io..Read$GT$11read_to_end17h38999a681cc6c5b5E", scope: !156, file: !39, line: 463, type: !157, scopeLine: 463, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) +!156 = !DINamespace(name: "{impl#7}", scope: !36) +!157 = distinct !DISubroutineType(types: !3) +!158 = distinct !DILocation(line: 430, column: 9, scope: !159) +!159 = distinct !DISubprogram(name: "read_to_end", linkageName: "_ZN55_$LT$std..io..stdio..Stdin$u20$as$u20$std..io..Read$GT$11read_to_end17haba70a09681d41d3E", scope: !160, file: !39, line: 429, type: !161, scopeLine: 429, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !3, retainedNodes: !3) +!160 = !DINamespace(name: "{impl#5}", scope: !36) +!161 = !DISubroutineType(types: !3) diff --git a/llvm/test/CodeGen/X86/zero-call-used-regs-i386.ll b/llvm/test/CodeGen/X86/zero-call-used-regs-i386.ll new file mode 100644 index 000000000000..33e501ca8503 --- /dev/null +++ b/llvm/test/CodeGen/X86/zero-call-used-regs-i386.ll @@ -0,0 +1,112 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -opaque-pointers | FileCheck %s --check-prefix=I386 +; +; Make sure we don't zero out %eax when both %ah and %al are used. +; +; PR1766: https://github.com/ClangBuiltLinux/linux/issues/1766 + +%struct.maple_subtree_state = type { ptr } + +@mas_data_end_type = dso_local local_unnamed_addr global i32 0, align 4 +@ma_meta_end_mn_0_0_0_0_0_0 = dso_local local_unnamed_addr global i8 0, align 1 +@mt_pivots_0 = dso_local local_unnamed_addr global i8 0, align 1 +@mas_data_end___trans_tmp_2 = dso_local local_unnamed_addr global ptr null, align 4 +@mt_slots_0 = dso_local local_unnamed_addr global i8 0, align 1 + +define dso_local zeroext i1 @test1(ptr nocapture noundef readonly %0) local_unnamed_addr "zero-call-used-regs"="used-gpr" nounwind { +; I386-LABEL: test1: +; I386: # %bb.0: +; I386-NEXT: pushl %ebx +; I386-NEXT: subl $24, %esp +; I386-NEXT: movl {{[0-9]+}}(%esp), %eax +; I386-NEXT: movl (%eax), %eax +; I386-NEXT: movzbl (%eax), %ebx +; I386-NEXT: calll bar +; I386-NEXT: testb %al, %al +; I386-NEXT: # implicit-def: $al +; I386-NEXT: # kill: killed $al +; I386-NEXT: je .LBB0_6 +; I386-NEXT: # %bb.1: +; I386-NEXT: cmpl $0, mas_data_end_type +; I386-NEXT: je .LBB0_3 +; I386-NEXT: # %bb.2: +; I386-NEXT: movzbl ma_meta_end_mn_0_0_0_0_0_0, %eax +; I386-NEXT: movb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill +; I386-NEXT: jmp .LBB0_6 +; I386-NEXT: .LBB0_3: +; I386-NEXT: movb mt_pivots_0, %ah +; I386-NEXT: movb %ah, %al +; I386-NEXT: decb %al +; I386-NEXT: movl mas_data_end___trans_tmp_2, %ecx +; I386-NEXT: movsbl %al, %edx +; I386-NEXT: cmpl $0, (%ecx,%edx,4) +; I386-NEXT: je .LBB0_5 +; I386-NEXT: # %bb.4: +; I386-NEXT: movb %al, %ah +; I386-NEXT: .LBB0_5: +; I386-NEXT: movb %ah, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill +; I386-NEXT: .LBB0_6: +; I386-NEXT: movb mt_slots_0, %bh +; I386-NEXT: leal {{[0-9]+}}(%esp), %eax +; I386-NEXT: movl %eax, (%esp) +; I386-NEXT: calll baz +; I386-NEXT: subl $4, %esp +; I386-NEXT: cmpb %bh, %bl +; I386-NEXT: jae .LBB0_8 +; I386-NEXT: # %bb.7: +; I386-NEXT: movsbl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 1-byte Folded Reload +; I386-NEXT: movl %eax, (%esp) +; I386-NEXT: calll gaz +; I386-NEXT: .LBB0_8: +; I386-NEXT: movb $1, %al +; I386-NEXT: addl $24, %esp +; I386-NEXT: popl %ebx +; I386-NEXT: xorl %ecx, %ecx +; I386-NEXT: xorl %edx, %edx +; I386-NEXT: retl + %2 = alloca %struct.maple_subtree_state, align 4 + %3 = load ptr, ptr %0, align 4 + %4 = load i8, ptr %3, align 1 + %5 = tail call zeroext i1 @bar() + br i1 %5, label %6, label %20 + +6: ; preds = %1 + %7 = load i32, ptr @mas_data_end_type, align 4 + %8 = icmp eq i32 %7, 0 + br i1 %8, label %11, label %9 + +9: ; preds = %6 + %10 = load i8, ptr @ma_meta_end_mn_0_0_0_0_0_0, align 1 + br label %20 + +11: ; preds = %6 + %12 = load i8, ptr @mt_pivots_0, align 1 + %13 = add i8 %12, -1 + %14 = load ptr, ptr @mas_data_end___trans_tmp_2, align 4 + %15 = sext i8 %13 to i32 + %16 = getelementptr inbounds [1 x i32], ptr %14, i32 0, i32 %15 + %17 = load i32, ptr %16, align 4 + %18 = icmp eq i32 %17, 0 + %19 = select i1 %18, i8 %12, i8 %13 + br label %20 + +20: ; preds = %11, %9, %1 + %21 = phi i8 [ undef, %1 ], [ %10, %9 ], [ %19, %11 ] + %22 = load i8, ptr @mt_slots_0, align 1 + call void @baz(ptr nonnull sret(%struct.maple_subtree_state) align 4 %2) + %23 = icmp ult i8 %4, %22 + br i1 %23, label %24, label %25 + +24: ; preds = %20 + call void @gaz(i8 noundef signext %21) + br label %25 + +25: ; preds = %20, %24 + ret i1 true +} + +declare dso_local zeroext i1 @bar(...) local_unnamed_addr + +declare dso_local void @baz(ptr sret(%struct.maple_subtree_state) align 4, ...) local_unnamed_addr + +declare dso_local void @gaz(i8 noundef signext) local_unnamed_addr diff --git a/llvm/utils/gn/secondary/llvm/version.gni b/llvm/utils/gn/secondary/llvm/version.gni index 00e1dc6f1411..d485a133f921 100644 --- a/llvm/utils/gn/secondary/llvm/version.gni +++ b/llvm/utils/gn/secondary/llvm/version.gni @@ -1,4 +1,4 @@ llvm_version_major = 15 llvm_version_minor = 0 -llvm_version_patch = 6 +llvm_version_patch = 7 llvm_version = "$llvm_version_major.$llvm_version_minor.$llvm_version_patch" diff --git a/llvm/utils/lit/lit/__init__.py b/llvm/utils/lit/lit/__init__.py index b34d17b9dc47..928d6db8d3cd 100644 --- a/llvm/utils/lit/lit/__init__.py +++ b/llvm/utils/lit/lit/__init__.py @@ -2,7 +2,7 @@ __author__ = 'Daniel Dunbar' __email__ = 'daniel@minormatter.com' -__versioninfo__ = (15, 0, 6) +__versioninfo__ = (15, 0, 7) __version__ = '.'.join(str(v) for v in __versioninfo__) + 'dev' __all__ = [] diff --git a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel index 5ee87d516519..59932954c949 100644 --- a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel @@ -358,11 +358,11 @@ genrule( name = "basic_version_gen", outs = ["include/clang/Basic/Version.inc"], cmd = ( - "echo '#define CLANG_VERSION 15.0.6' >> $@\n" + + "echo '#define CLANG_VERSION 15.0.7' >> $@\n" + "echo '#define CLANG_VERSION_MAJOR 15' >> $@\n" + "echo '#define CLANG_VERSION_MINOR 0' >> $@\n" + - "echo '#define CLANG_VERSION_PATCHLEVEL 6' >> $@\n" + - "echo '#define CLANG_VERSION_STRING \"15.0.6\"' >> $@\n" + "echo '#define CLANG_VERSION_PATCHLEVEL 7' >> $@\n" + + "echo '#define CLANG_VERSION_STRING \"15.0.7\"' >> $@\n" ), ) diff --git a/utils/bazel/llvm-project-overlay/clang/include/clang/Config/config.h b/utils/bazel/llvm-project-overlay/clang/include/clang/Config/config.h index ff4feb2b4af9..5ee35630d35a 100644 --- a/utils/bazel/llvm-project-overlay/clang/include/clang/Config/config.h +++ b/utils/bazel/llvm-project-overlay/clang/include/clang/Config/config.h @@ -93,7 +93,7 @@ /* CLANG_HAVE_RLIMITS defined conditionally below */ /* The LLVM product name and version */ -#define BACKEND_PACKAGE_STRING "LLVM 15.0.6" +#define BACKEND_PACKAGE_STRING "LLVM 15.0.7" /* Linker version detected at compile time. */ /* #undef HOST_LINK_VERSION */ diff --git a/utils/bazel/llvm-project-overlay/lld/BUILD.bazel b/utils/bazel/llvm-project-overlay/lld/BUILD.bazel index 6ba06c794413..06b57f39e333 100644 --- a/utils/bazel/llvm-project-overlay/lld/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/lld/BUILD.bazel @@ -13,7 +13,7 @@ package( genrule( name = "config_version_gen", outs = ["include/lld/Common/Version.inc"], - cmd = "echo '#define LLD_VERSION_STRING \"15.0.6\"' > $@", + cmd = "echo '#define LLD_VERSION_STRING \"15.0.7\"' > $@", ) genrule( diff --git a/utils/bazel/llvm-project-overlay/llvm/include/llvm/Config/llvm-config.h b/utils/bazel/llvm-project-overlay/llvm/include/llvm/Config/llvm-config.h index a44e9f60c0e1..1d5c3a4e879b 100644 --- a/utils/bazel/llvm-project-overlay/llvm/include/llvm/Config/llvm-config.h +++ b/utils/bazel/llvm-project-overlay/llvm/include/llvm/Config/llvm-config.h @@ -80,10 +80,10 @@ #define LLVM_VERSION_MINOR 0 /* Patch version of the LLVM API */ -#define LLVM_VERSION_PATCH 6 +#define LLVM_VERSION_PATCH 7 /* LLVM version string */ -#define LLVM_VERSION_STRING "15.0.6" +#define LLVM_VERSION_STRING "15.0.7" /* Whether LLVM records statistics for use with GetStatistics(), * PrintStatistics() or PrintStatisticsJSON()