601 changes: 601 additions & 0 deletions libc/src/math/nvptx/CMakeLists.txt

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions libc/src/math/nvptx/llrint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(long long, llrint, (double x)) {
return static_cast<long long>(__builtin_rint(x));
}
LLVM_LIBC_FUNCTION(long long, llrint, (double x)) { return __nv_llrint(x); }

} // namespace LIBC_NAMESPACE
4 changes: 1 addition & 3 deletions libc/src/math/nvptx/llrintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(long long, llrintf, (float x)) {
return static_cast<long long>(__builtin_rintf(x));
}
LLVM_LIBC_FUNCTION(long long, llrintf, (float x)) { return __nv_llrintf(x); }

} // namespace LIBC_NAMESPACE
4 changes: 1 addition & 3 deletions libc/src/math/nvptx/lrint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(long, lrint, (double x)) {
return static_cast<long>(__builtin_rint(x));
}
LLVM_LIBC_FUNCTION(long, lrint, (double x)) { return __nv_lrint(x); }

} // namespace LIBC_NAMESPACE
7 changes: 3 additions & 4 deletions libc/src/stdio/fopencookie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class CookieFile : public LIBC_NAMESPACE::File {

static FileIOResult cookie_write(File *f, const void *data, size_t size);
static FileIOResult cookie_read(File *f, void *data, size_t size);
static ErrorOr<long> cookie_seek(File *f, long offset, int whence);
static ErrorOr<off_t> cookie_seek(File *f, off_t offset, int whence);
static int cookie_close(File *f);

public:
Expand Down Expand Up @@ -52,7 +52,7 @@ FileIOResult CookieFile::cookie_read(File *f, void *data, size_t size) {
reinterpret_cast<char *>(data), size);
}

ErrorOr<long> CookieFile::cookie_seek(File *f, long offset, int whence) {
ErrorOr<off_t> CookieFile::cookie_seek(File *f, off_t offset, int whence) {
auto cookie_file = reinterpret_cast<CookieFile *>(f);
if (cookie_file->ops.seek == nullptr) {
return Error(EINVAL);
Expand All @@ -61,8 +61,7 @@ ErrorOr<long> CookieFile::cookie_seek(File *f, long offset, int whence) {
int result = cookie_file->ops.seek(cookie_file->cookie, &offset64, whence);
if (result == 0)
return offset64;
else
return -1;
return -1;
}

int CookieFile::cookie_close(File *f) {
Expand Down
6 changes: 5 additions & 1 deletion libc/src/stdio/generic/ftell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ LLVM_LIBC_FUNCTION(long, ftell, (::FILE * stream)) {
libc_errno = result.error();
return -1;
}
return result.value();
// tell() returns an off_t (64-bit signed integer), but this function returns
// a long (32-bit signed integer in 32-bit systems). We add a cast here to
// silence a "implicit conversion loses integer precision" warning when
// compiling for 32-bit systems.
return static_cast<long>(result.value());
}

} // namespace LIBC_NAMESPACE
5 changes: 4 additions & 1 deletion libc/src/sys/mman/linux/mmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@ LLVM_LIBC_FUNCTION(void *, mmap,
#error "mmap or mmap2 syscalls not available."
#endif

// We add an explicit cast to silence a "implicit conversion loses integer
// precision" warning when compiling for 32-bit systems.
long mmap_offset = static_cast<long>(offset);
long ret =
LIBC_NAMESPACE::syscall_impl(syscall_number, reinterpret_cast<long>(addr),
size, prot, flags, fd, offset);
size, prot, flags, fd, mmap_offset);

// The mmap/mmap2 syscalls return negative values on error. These negative
// values are actually the negative values of the error codes. So, fix them
Expand Down
24 changes: 15 additions & 9 deletions libc/src/unistd/linux/pread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,21 @@ namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(ssize_t, pread,
(int fd, void *buf, size_t count, off_t offset)) {
#ifdef LIBC_TARGET_ARCH_IS_RISCV32
static_assert(sizeof(off_t) == 8);
ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(
SYS_pread64, fd, buf, count, (long)offset,
(long)(((uint64_t)(offset)) >> 32));
#else
ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_pread64, fd, buf,
count, offset);
#endif
ssize_t ret;
if constexpr (sizeof(long) == sizeof(uint32_t) &&
sizeof(off_t) == sizeof(uint64_t)) {
// This is a 32-bit system with a 64-bit offset, offset must be split.
const uint64_t bits = cpp::bit_cast<uint64_t>(offset);
const uint32_t lo = bits & UINT32_MAX;
const uint32_t hi = bits >> 32;
const long offset_low = cpp::bit_cast<long>(static_cast<long>(lo));
const long offset_high = cpp::bit_cast<long>(static_cast<long>(hi));
ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_pread64, fd, buf, count,
offset_low, offset_high);
} else {
ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_pread64, fd, buf, count,
offset);
}
// The cast is important since there is a check that dereferences the pointer
// which fails on void*.
MSAN_UNPOISON(reinterpret_cast<char *>(buf), count);
Expand Down
26 changes: 17 additions & 9 deletions libc/src/unistd/linux/pwrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,23 @@ namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(ssize_t, pwrite,
(int fd, const void *buf, size_t count, off_t offset)) {
#ifdef LIBC_TARGET_ARCH_IS_RISCV32
static_assert(sizeof(off_t) == 8);
ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(
SYS_pwrite64, fd, buf, count, (long)offset,
(long)(((uint64_t)(offset)) >> 32));
#else
ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_pwrite64, fd, buf,
count, offset);
#endif

ssize_t ret;
if constexpr (sizeof(long) == sizeof(uint32_t) &&
sizeof(off_t) == sizeof(uint64_t)) {
// This is a 32-bit system with a 64-bit offset, offset must be split.
const uint64_t bits = cpp::bit_cast<uint64_t>(offset);
const uint32_t lo = bits & UINT32_MAX;
const uint32_t hi = bits >> 32;
const long offset_low = cpp::bit_cast<long>(static_cast<long>(lo));
const long offset_high = cpp::bit_cast<long>(static_cast<long>(hi));
ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_pwrite64, fd, buf, count,
offset_low, offset_high);
} else {
ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_pwrite64, fd, buf, count,
offset);
}

if (ret < 0) {
libc_errno = static_cast<int>(-ret);
return -1;
Expand Down
8 changes: 4 additions & 4 deletions libc/test/src/__support/File/file_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class StringFile : public File {
static FileIOResult str_read(LIBC_NAMESPACE::File *f, void *data, size_t len);
static FileIOResult str_write(LIBC_NAMESPACE::File *f, const void *data,
size_t len);
static ErrorOr<long> str_seek(LIBC_NAMESPACE::File *f, long offset,
int whence);
static ErrorOr<off_t> str_seek(LIBC_NAMESPACE::File *f, off_t offset,
int whence);
static int str_close(LIBC_NAMESPACE::File *f) {
delete reinterpret_cast<StringFile *>(f);
return 0;
Expand Down Expand Up @@ -93,8 +93,8 @@ FileIOResult StringFile::str_write(LIBC_NAMESPACE::File *f, const void *data,
return i;
}

ErrorOr<long> StringFile::str_seek(LIBC_NAMESPACE::File *f, long offset,
int whence) {
ErrorOr<off_t> StringFile::str_seek(LIBC_NAMESPACE::File *f, off_t offset,
int whence) {
StringFile *sf = static_cast<StringFile *>(f);
if (whence == SEEK_SET)
sf->pos = offset;
Expand Down
12 changes: 12 additions & 0 deletions libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_bitset`` ``202306L``
---------------------------------------------------------- -----------------
``__cpp_lib_constexpr_new`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_constrained_equality`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_copyable_function`` *unimplemented*
Expand Down Expand Up @@ -436,12 +438,20 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_hazard_pointer`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_inplace_vector`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_is_virtual_base_of`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_is_within_lifetime`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_linalg`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_optional_range_support`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_out_ptr`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_philox_engine`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_ranges_concat`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_ratio`` ``202306L``
Expand All @@ -452,6 +462,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_saturation_arithmetic`` ``202311L``
---------------------------------------------------------- -----------------
``__cpp_lib_senders`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_smart_ptr_owner_equality`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_span_at`` ``202311L``
Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/Status/Cxx2c.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Paper Status
.. [#note-P2510R3] This paper is applied as DR against C++20. (MSVC STL and libstdc++ will do the same.)
.. [#note-P3142R0] This paper is applied as DR against C++23. (MSVC STL and libstdc++ will do the same.)
.. [#note-P2944R3] Implemented comparisons for ``reference_wrapper`` only.
.. [#note-P2422R1] Libc++ keeps the ``nodiscard`` attributes as a conforming extension.
.. _issues-status-cxx2c:

Expand Down
15 changes: 14 additions & 1 deletion libcxx/docs/Status/Cxx2cIssues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,20 @@
"`4053 <https://wg21.link/LWG4053>`__","Unary call to ``std::views::repeat`` does not decay the argument","Tokyo March 2024","|Complete|","19.0","|ranges|"
"`4054 <https://wg21.link/LWG4054>`__","Repeating a ``repeat_view`` should repeat the view","Tokyo March 2024","|Complete|","19.0","|ranges|"
"","","","","",""
"`3944 <https://wg21.link/LWG3944>`__","Formatters converting sequences of ``char`` to sequences of ``wchar_t``","St. Louis June 2024","","","|format|"
"`4060 <https://wg21.link/LWG4060>`__","``submdspan`` preconditions do not forbid creating invalid pointer","St. Louis June 2024","","",""
"`4061 <https://wg21.link/LWG4061>`__","Should ``std::basic_format_context`` be default-constructible/copyable/movable?","St. Louis June 2024","","","|format|"
"`4071 <https://wg21.link/LWG4071>`__","``reference_wrapper`` comparisons are not SFINAE-friendly","St. Louis June 2024","|Complete|","19.0",""
"`4074 <https://wg21.link/LWG4074>`__","``compatible-joinable-ranges`` is underconstrained","St. Louis June 2024","","","|ranges|"
"`4076 <https://wg21.link/LWG4076>`__","``concat_view`` should be freestanding","St. Louis June 2024","","",""
"`4079 <https://wg21.link/LWG4079>`__","Missing Preconditions in ``concat_view::iterator``\`s conversion constructor","St. Louis June 2024","","","|ranges|"
"`4082 <https://wg21.link/LWG4082>`__","``views::concat(r)`` is well-formed when ``r`` is an ``output_range``","St. Louis June 2024","","","|ranges|"
"`4083 <https://wg21.link/LWG4083>`__","``views::as_rvalue`` should reject non-input ranges","St. Louis June 2024","","","|ranges|"
"`4096 <https://wg21.link/LWG4096>`__","``views::iota(views::iota(0))`` should be rejected","St. Louis June 2024","","","|ranges|"
"`4098 <https://wg21.link/LWG4098>`__","``views::adjacent<0>`` should reject non-forward ranges","St. Louis June 2024","","","|ranges|"
"`4105 <https://wg21.link/LWG4105>`__","``ranges::ends_with``\`s Returns misses difference casting","St. Louis June 2024","","","|ranges|"
"`4106 <https://wg21.link/LWG4106>`__","``basic_format_args`` should not be default-constructible","St. Louis June 2024","","","|format|"
"","","","","",""
"`3343 <https://wg21.link/LWG3343>`__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Yet Adopted","|Complete|","16.0",""
"XXXX","","The sys_info range should be affected by save","Not Yet Adopted","|Complete|","19.0"
"`4071 <https://wg21.link/LWG4071>`__","","``reference_wrapper`` comparisons are not SFINAE-friendly","Not Yet Adopted","|Complete|","19.0"
"","","","","",""
13 changes: 13 additions & 0 deletions libcxx/docs/Status/Cxx2cPapers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,16 @@
"`P2642R6 <https://wg21.link/P2642R6>`__","LWG","Padded ``mdspan`` layouts","Tokyo March 2024","","",""
"`P3029R1 <https://wg21.link/P3029R1>`__","LWG","Better ``mdspan``'s CTAD","Tokyo March 2024","|Complete|","19.0",""
"","","","","","",""
"`P2747R2 <https://wg21.link/P2747R2>`__","CWG","``constexpr`` placement new","St. Louis June 2024","","",""
"`P2997R1 <https://wg21.link/P2997R1>`__","LWG","Removing the common reference requirement from the indirectly invocable concepts","St. Louis June 2024","","",""
"`P2389R2 <https://wg21.link/P2389R2>`__","LWG","``dextents`` Index Type Parameter","St. Louis June 2024","","",""
"`P3168R2 <https://wg21.link/P3168R2>`__","LWG","Give ``std::optional`` Range Support","St. Louis June 2024","","","|ranges|"
"`P3217R0 <https://wg21.link/P3217R0>`__","LWG","Adjoints to 'Enabling list-initialization for algorithms': find_last","St. Louis June 2024","","",""
"`P2985R0 <https://wg21.link/P2985R0>`__","LWG","A type trait for detecting virtual base classes","St. Louis June 2024","","",""
"`P0843R14 <https://wg21.link/P0843R14>`__","LWG","``inplace_vector``","St. Louis June 2024","","",""
"`P3235R3 <https://wg21.link/P3235R3>`__","LWG","``std::print`` more types faster with less memory","St. Louis June 2024","","","|format| |DR|"
"`P2968R2 <https://wg21.link/P2968R2>`__","LWG","Make ``std::ignore`` a first-class object","St. Louis June 2024","","",""
"`P2075R6 <https://wg21.link/P2075R6>`__","LWG","Philox as an extension of the C++ RNG engines","St. Louis June 2024","","",""
"`P2422R1 <https://wg21.link/P2422R1>`__","LWG","Remove ``nodiscard`` annotations from the standard library specification","St. Louis June 2024","|Complete| [#note-P2422R1]_","19.0",""
"`P2300R10 <https://wg21.link/P2300R10>`__","LWG","``std::execution``","St. Louis June 2024","","",""
"","","","","","",""
12 changes: 12 additions & 0 deletions libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ __cpp_lib_constexpr_functional 201907L <functional>
__cpp_lib_constexpr_iterator 201811L <iterator>
__cpp_lib_constexpr_memory 202202L <memory>
201811L // C++20
__cpp_lib_constexpr_new 202406L <new>
__cpp_lib_constexpr_numeric 201911L <numeric>
__cpp_lib_constexpr_string 201907L <string>
__cpp_lib_constexpr_string_view 201811L <string_view>
Expand Down Expand Up @@ -125,6 +126,7 @@ __cpp_lib_has_unique_object_representations 201606L <type_traits>
__cpp_lib_hazard_pointer 202306L <hazard_pointer>
__cpp_lib_hypot 201603L <cmath>
__cpp_lib_incomplete_container_elements 201505L <forward_list> <list> <vector>
__cpp_lib_inplace_vector 202406L <inplace_vector>
__cpp_lib_int_pow2 202002L <bit>
__cpp_lib_integer_comparison_functions 202002L <utility>
__cpp_lib_integer_sequence 201304L <utility>
Expand All @@ -143,6 +145,7 @@ __cpp_lib_is_null_pointer 201309L <type_traits>
__cpp_lib_is_pointer_interconvertible 201907L <type_traits>
__cpp_lib_is_scoped_enum 202011L <type_traits>
__cpp_lib_is_swappable 201603L <type_traits>
__cpp_lib_is_virtual_base_of 202406L <type_traits>
__cpp_lib_is_within_lifetime 202306L <type_traits>
__cpp_lib_jthread 201911L <stop_token> <thread>
__cpp_lib_latch 201907L <latch>
Expand Down Expand Up @@ -170,9 +173,11 @@ __cpp_lib_not_fn 201603L <functional>
__cpp_lib_null_iterators 201304L <iterator>
__cpp_lib_optional 202110L <optional>
201606L // C++17
__cpp_lib_optional_range_support 202406L <optional>
__cpp_lib_out_ptr 202311L <memory>
202106L // C++23
__cpp_lib_parallel_algorithm 201603L <algorithm> <numeric>
__cpp_lib_philox_engine 202406L <random>
__cpp_lib_polymorphic_allocator 201902L <memory_resource>
__cpp_lib_print 202207L <ostream> <print>
__cpp_lib_quoted_string_io 201304L <iomanip>
Expand Down Expand Up @@ -203,6 +208,7 @@ __cpp_lib_sample 201603L <algorithm>
__cpp_lib_saturation_arithmetic 202311L <numeric>
__cpp_lib_scoped_lock 201703L <mutex>
__cpp_lib_semaphore 201907L <semaphore>
__cpp_lib_senders 202406L <execution>
__cpp_lib_shared_mutex 201505L <shared_mutex>
__cpp_lib_shared_ptr_arrays 201707L <memory>
201611L // C++17
Expand Down Expand Up @@ -500,6 +506,7 @@ __cpp_lib_void_t 201411L <type_traits>
# undef __cpp_lib_bind_front
# define __cpp_lib_bind_front 202306L
# define __cpp_lib_bitset 202306L
// # define __cpp_lib_constexpr_new 202406L
// # define __cpp_lib_constrained_equality 202403L
// # define __cpp_lib_copyable_function 202306L
// # define __cpp_lib_debugging 202311L
Expand All @@ -519,15 +526,20 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_function_ref 202306L
// # define __cpp_lib_generate_random 202403L
// # define __cpp_lib_hazard_pointer 202306L
// # define __cpp_lib_inplace_vector 202406L
// # define __cpp_lib_is_virtual_base_of 202406L
// # define __cpp_lib_is_within_lifetime 202306L
// # define __cpp_lib_linalg 202311L
// # define __cpp_lib_optional_range_support 202406L
# undef __cpp_lib_out_ptr
// # define __cpp_lib_out_ptr 202311L
// # define __cpp_lib_philox_engine 202406L
// # define __cpp_lib_ranges_concat 202403L
# define __cpp_lib_ratio 202306L
// # define __cpp_lib_rcu 202306L
# define __cpp_lib_reference_wrapper 202403L
# define __cpp_lib_saturation_arithmetic 202311L
// # define __cpp_lib_senders 202406L
// # define __cpp_lib_smart_ptr_owner_equality 202306L
# define __cpp_lib_span_at 202311L
# define __cpp_lib_span_initializer_list 202311L
Expand Down
3 changes: 3 additions & 0 deletions libcxx/modules/std.compat.cppm.in
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ module;
# if __has_include(<hazard_pointer>)
# error "please update the header information for <hazard_pointer> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<hazard_pointer>)
# if __has_include(<inplace_vector>)
# error "please update the header information for <inplace_vector> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<inplace_vector>)
# if __has_include(<linalg>)
# error "please update the header information for <linalg> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<linalg>)
Expand Down
3 changes: 3 additions & 0 deletions libcxx/modules/std.cppm.in
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ module;
# if __has_include(<hazard_pointer>)
# error "please update the header information for <hazard_pointer> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<hazard_pointer>)
# if __has_include(<inplace_vector>)
# error "please update the header information for <inplace_vector> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<inplace_vector>)
# if __has_include(<linalg>)
# error "please update the header information for <linalg> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<linalg>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
/* Constant Value
__cpp_lib_execution 201603L [C++17]
201902L [C++20]
__cpp_lib_senders 202406L [C++26]
*/

#include <execution>
Expand All @@ -29,12 +30,20 @@
# error "__cpp_lib_execution should not be defined before c++17"
# endif

# ifdef __cpp_lib_senders
# error "__cpp_lib_senders should not be defined before c++26"
# endif

#elif TEST_STD_VER == 14

# ifdef __cpp_lib_execution
# error "__cpp_lib_execution should not be defined before c++17"
# endif

# ifdef __cpp_lib_senders
# error "__cpp_lib_senders should not be defined before c++26"
# endif

#elif TEST_STD_VER == 17

# if !defined(_LIBCPP_VERSION)
Expand All @@ -50,6 +59,10 @@
# endif
# endif

# ifdef __cpp_lib_senders
# error "__cpp_lib_senders should not be defined before c++26"
# endif

#elif TEST_STD_VER == 20

# if !defined(_LIBCPP_VERSION)
Expand All @@ -65,6 +78,10 @@
# endif
# endif

# ifdef __cpp_lib_senders
# error "__cpp_lib_senders should not be defined before c++26"
# endif

#elif TEST_STD_VER == 23

# if !defined(_LIBCPP_VERSION)
Expand All @@ -80,6 +97,10 @@
# endif
# endif

# ifdef __cpp_lib_senders
# error "__cpp_lib_senders should not be defined before c++26"
# endif

#elif TEST_STD_VER > 23

# if !defined(_LIBCPP_VERSION)
Expand All @@ -95,5 +116,18 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_senders
# error "__cpp_lib_senders should be defined in c++26"
# endif
# if __cpp_lib_senders != 202406L
# error "__cpp_lib_senders should have the value 202406L in c++26"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_senders
# error "__cpp_lib_senders should not be defined because it is unimplemented in libc++!"
# endif
# endif

#endif // TEST_STD_VER > 23

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
// Test the feature test macros defined by <new>

/* Constant Value
__cpp_lib_constexpr_new 202406L [C++26]
__cpp_lib_destroying_delete 201806L [C++20]
__cpp_lib_hardware_interference_size 201703L [C++17]
__cpp_lib_launder 201606L [C++17]
Expand All @@ -26,6 +27,10 @@

#if TEST_STD_VER < 14

# ifdef __cpp_lib_constexpr_new
# error "__cpp_lib_constexpr_new should not be defined before c++26"
# endif

# ifdef __cpp_lib_destroying_delete
# error "__cpp_lib_destroying_delete should not be defined before c++20"
# endif
Expand All @@ -40,6 +45,10 @@

#elif TEST_STD_VER == 14

# ifdef __cpp_lib_constexpr_new
# error "__cpp_lib_constexpr_new should not be defined before c++26"
# endif

# ifdef __cpp_lib_destroying_delete
# error "__cpp_lib_destroying_delete should not be defined before c++20"
# endif
Expand All @@ -54,6 +63,10 @@

#elif TEST_STD_VER == 17

# ifdef __cpp_lib_constexpr_new
# error "__cpp_lib_constexpr_new should not be defined before c++26"
# endif

# ifdef __cpp_lib_destroying_delete
# error "__cpp_lib_destroying_delete should not be defined before c++20"
# endif
Expand All @@ -80,6 +93,10 @@

#elif TEST_STD_VER == 20

# ifdef __cpp_lib_constexpr_new
# error "__cpp_lib_constexpr_new should not be defined before c++26"
# endif

# if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
# ifndef __cpp_lib_destroying_delete
# error "__cpp_lib_destroying_delete should be defined in c++20"
Expand Down Expand Up @@ -115,6 +132,10 @@

#elif TEST_STD_VER == 23

# ifdef __cpp_lib_constexpr_new
# error "__cpp_lib_constexpr_new should not be defined before c++26"
# endif

# if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
# ifndef __cpp_lib_destroying_delete
# error "__cpp_lib_destroying_delete should be defined in c++23"
Expand Down Expand Up @@ -150,6 +171,19 @@

#elif TEST_STD_VER > 23

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_constexpr_new
# error "__cpp_lib_constexpr_new should be defined in c++26"
# endif
# if __cpp_lib_constexpr_new != 202406L
# error "__cpp_lib_constexpr_new should have the value 202406L in c++26"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_constexpr_new
# error "__cpp_lib_constexpr_new should not be defined because it is unimplemented in libc++!"
# endif
# endif

# if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
# ifndef __cpp_lib_destroying_delete
# error "__cpp_lib_destroying_delete should be defined in c++26"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@

// Test the feature test macros defined by <optional>

/* Constant Value
__cpp_lib_constrained_equality 202403L [C++26]
__cpp_lib_freestanding_optional 202311L [C++26]
__cpp_lib_optional 201606L [C++17]
202110L [C++23]
/* Constant Value
__cpp_lib_constrained_equality 202403L [C++26]
__cpp_lib_freestanding_optional 202311L [C++26]
__cpp_lib_optional 201606L [C++17]
202110L [C++23]
__cpp_lib_optional_range_support 202406L [C++26]
*/

#include <optional>
Expand All @@ -39,6 +40,10 @@
# error "__cpp_lib_optional should not be defined before c++17"
# endif

# ifdef __cpp_lib_optional_range_support
# error "__cpp_lib_optional_range_support should not be defined before c++26"
# endif

#elif TEST_STD_VER == 14

# ifdef __cpp_lib_constrained_equality
Expand All @@ -53,6 +58,10 @@
# error "__cpp_lib_optional should not be defined before c++17"
# endif

# ifdef __cpp_lib_optional_range_support
# error "__cpp_lib_optional_range_support should not be defined before c++26"
# endif

#elif TEST_STD_VER == 17

# ifdef __cpp_lib_constrained_equality
Expand All @@ -70,6 +79,10 @@
# error "__cpp_lib_optional should have the value 201606L in c++17"
# endif

# ifdef __cpp_lib_optional_range_support
# error "__cpp_lib_optional_range_support should not be defined before c++26"
# endif

#elif TEST_STD_VER == 20

# ifdef __cpp_lib_constrained_equality
Expand All @@ -87,6 +100,10 @@
# error "__cpp_lib_optional should have the value 201606L in c++20"
# endif

# ifdef __cpp_lib_optional_range_support
# error "__cpp_lib_optional_range_support should not be defined before c++26"
# endif

#elif TEST_STD_VER == 23

# ifdef __cpp_lib_constrained_equality
Expand All @@ -104,6 +121,10 @@
# error "__cpp_lib_optional should have the value 202110L in c++23"
# endif

# ifdef __cpp_lib_optional_range_support
# error "__cpp_lib_optional_range_support should not be defined before c++26"
# endif

#elif TEST_STD_VER > 23

# if !defined(_LIBCPP_VERSION)
Expand Down Expand Up @@ -139,5 +160,18 @@
# error "__cpp_lib_optional should have the value 202110L in c++26"
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_optional_range_support
# error "__cpp_lib_optional_range_support should be defined in c++26"
# endif
# if __cpp_lib_optional_range_support != 202406L
# error "__cpp_lib_optional_range_support should have the value 202406L in c++26"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_optional_range_support
# error "__cpp_lib_optional_range_support should not be defined because it is unimplemented in libc++!"
# endif
# endif

#endif // TEST_STD_VER > 23

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

/* Constant Value
__cpp_lib_generate_random 202403L [C++26]
__cpp_lib_philox_engine 202406L [C++26]
*/

#include <random>
Expand All @@ -28,30 +29,50 @@
# error "__cpp_lib_generate_random should not be defined before c++26"
# endif

# ifdef __cpp_lib_philox_engine
# error "__cpp_lib_philox_engine should not be defined before c++26"
# endif

#elif TEST_STD_VER == 14

# ifdef __cpp_lib_generate_random
# error "__cpp_lib_generate_random should not be defined before c++26"
# endif

# ifdef __cpp_lib_philox_engine
# error "__cpp_lib_philox_engine should not be defined before c++26"
# endif

#elif TEST_STD_VER == 17

# ifdef __cpp_lib_generate_random
# error "__cpp_lib_generate_random should not be defined before c++26"
# endif

# ifdef __cpp_lib_philox_engine
# error "__cpp_lib_philox_engine should not be defined before c++26"
# endif

#elif TEST_STD_VER == 20

# ifdef __cpp_lib_generate_random
# error "__cpp_lib_generate_random should not be defined before c++26"
# endif

# ifdef __cpp_lib_philox_engine
# error "__cpp_lib_philox_engine should not be defined before c++26"
# endif

#elif TEST_STD_VER == 23

# ifdef __cpp_lib_generate_random
# error "__cpp_lib_generate_random should not be defined before c++26"
# endif

# ifdef __cpp_lib_philox_engine
# error "__cpp_lib_philox_engine should not be defined before c++26"
# endif

#elif TEST_STD_VER > 23

# if !defined(_LIBCPP_VERSION)
Expand All @@ -67,5 +88,18 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_philox_engine
# error "__cpp_lib_philox_engine should be defined in c++26"
# endif
# if __cpp_lib_philox_engine != 202406L
# error "__cpp_lib_philox_engine should have the value 202406L in c++26"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_philox_engine
# error "__cpp_lib_philox_engine should not be defined because it is unimplemented in libc++!"
# endif
# endif

#endif // TEST_STD_VER > 23

Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
__cpp_lib_is_pointer_interconvertible 201907L [C++20]
__cpp_lib_is_scoped_enum 202011L [C++23]
__cpp_lib_is_swappable 201603L [C++17]
__cpp_lib_is_virtual_base_of 202406L [C++26]
__cpp_lib_is_within_lifetime 202306L [C++26]
__cpp_lib_logical_traits 201510L [C++17]
__cpp_lib_reference_from_temporary 202202L [C++23]
Expand Down Expand Up @@ -102,6 +103,10 @@
# error "__cpp_lib_is_swappable should not be defined before c++17"
# endif

# ifdef __cpp_lib_is_virtual_base_of
# error "__cpp_lib_is_virtual_base_of should not be defined before c++26"
# endif

# ifdef __cpp_lib_is_within_lifetime
# error "__cpp_lib_is_within_lifetime should not be defined before c++26"
# endif
Expand Down Expand Up @@ -205,6 +210,10 @@
# error "__cpp_lib_is_swappable should not be defined before c++17"
# endif

# ifdef __cpp_lib_is_virtual_base_of
# error "__cpp_lib_is_virtual_base_of should not be defined before c++26"
# endif

# ifdef __cpp_lib_is_within_lifetime
# error "__cpp_lib_is_within_lifetime should not be defined before c++26"
# endif
Expand Down Expand Up @@ -329,6 +338,10 @@
# error "__cpp_lib_is_swappable should have the value 201603L in c++17"
# endif

# ifdef __cpp_lib_is_virtual_base_of
# error "__cpp_lib_is_virtual_base_of should not be defined before c++26"
# endif

# ifdef __cpp_lib_is_within_lifetime
# error "__cpp_lib_is_within_lifetime should not be defined before c++26"
# endif
Expand Down Expand Up @@ -489,6 +502,10 @@
# error "__cpp_lib_is_swappable should have the value 201603L in c++20"
# endif

# ifdef __cpp_lib_is_virtual_base_of
# error "__cpp_lib_is_virtual_base_of should not be defined before c++26"
# endif

# ifdef __cpp_lib_is_within_lifetime
# error "__cpp_lib_is_within_lifetime should not be defined before c++26"
# endif
Expand Down Expand Up @@ -658,6 +675,10 @@
# error "__cpp_lib_is_swappable should have the value 201603L in c++23"
# endif

# ifdef __cpp_lib_is_virtual_base_of
# error "__cpp_lib_is_virtual_base_of should not be defined before c++26"
# endif

# ifdef __cpp_lib_is_within_lifetime
# error "__cpp_lib_is_within_lifetime should not be defined before c++26"
# endif
Expand Down Expand Up @@ -836,6 +857,19 @@
# error "__cpp_lib_is_swappable should have the value 201603L in c++26"
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_is_virtual_base_of
# error "__cpp_lib_is_virtual_base_of should be defined in c++26"
# endif
# if __cpp_lib_is_virtual_base_of != 202406L
# error "__cpp_lib_is_virtual_base_of should have the value 202406L in c++26"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_is_virtual_base_of
# error "__cpp_lib_is_virtual_base_of should not be defined because it is unimplemented in libc++!"
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_is_within_lifetime
# error "__cpp_lib_is_within_lifetime should be defined in c++26"
Expand Down

Large diffs are not rendered by default.

52 changes: 50 additions & 2 deletions libcxx/utils/generate_feature_test_macro_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,12 @@ def add_version_header(tc):
"values": {"c++20": 201811, "c++23": 202202},
"headers": ["memory"],
},
{
"name": "__cpp_lib_constexpr_new",
"values": {"c++26": 202406}, # P2747R2 constexpr placement new
"headers": ["new"],
"unimplemented": True,
},
{
"name": "__cpp_lib_constexpr_numeric",
"values": {"c++20": 201911},
Expand Down Expand Up @@ -679,6 +685,12 @@ def add_version_header(tc):
"values": {"c++17": 201505},
"headers": ["forward_list", "list", "vector"],
},
{
"name": "__cpp_lib_inplace_vector",
"values": {"c++26": 202406}, # P0843R14 inplace_vector
"headers": ["inplace_vector"],
"unimplemented": True,
},
{
"name": "__cpp_lib_int_pow2",
"values": {"c++20": 202002},
Expand Down Expand Up @@ -771,6 +783,14 @@ def add_version_header(tc):
"values": {"c++17": 201603},
"headers": ["type_traits"],
},
{
"name": "__cpp_lib_is_virtual_base_of",
"values": {
"c++26": 202406 # P2985R0 A type trait for detecting virtual base classes
},
"headers": ["type_traits"],
"unimplemented": True,
},
{
"name": "__cpp_lib_is_within_lifetime",
# Note this name was changed from "__cpp_lib_within_lifetime" when the paper was adopted
Expand Down Expand Up @@ -851,7 +871,10 @@ def add_version_header(tc):
},
{
"name": "__cpp_lib_mdspan",
"values": {"c++23": 202207},
"values": {
"c++23": 202207,
# "c++26": 202406, # P2389R2 dextents Index Type Parameter
},
"headers": ["mdspan"],
},
{
Expand Down Expand Up @@ -918,6 +941,12 @@ def add_version_header(tc):
"values": {"c++17": 201606, "c++23": 202110},
"headers": ["optional"],
},
{
"name": "__cpp_lib_optional_range_support",
"values": {"c++26": 202406}, # P3168R2 Give std::optional Range Support
"headers": ["optional"],
"unimplemented": True,
},
{
"name": "__cpp_lib_out_ptr",
"values": {
Expand All @@ -933,6 +962,15 @@ def add_version_header(tc):
"headers": ["algorithm", "numeric"],
"unimplemented": True,
},
{
"name": "__cpp_lib_philox_engine",
"values": {
"c++26": 202406
}, # P2075R6 Philox as an extension of the C++ RNG engines
# Note the paper mentions 202310L as value, which differs from the typical procedure.
"headers": ["random"],
"unimplemented": True,
},
{
"name": "__cpp_lib_polymorphic_allocator",
"values": {"c++20": 201902},
Expand All @@ -945,6 +983,7 @@ def add_version_header(tc):
"values": {
"c++23": 202207,
# "c++26": 202403, # P3107R5: Permit an efficient implementation of std::print
# "c++26": 202406, # P3235R3 std::print more types faster with less memory
},
"headers": ["ostream", "print"],
},
Expand All @@ -957,7 +996,10 @@ def add_version_header(tc):
},
{
"name": "__cpp_lib_ranges",
"values": {"c++20": 202207},
"values": {
"c++20": 202207,
# "c++26": 202406, # P2997R1 Removing the common reference requirement from the indirectly invocable concepts
},
"headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
},
{
Expand Down Expand Up @@ -1103,6 +1145,12 @@ def add_version_header(tc):
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && (!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_SYNC)",
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
},
{
"name": "__cpp_lib_senders",
"values": {"c++26": 202406}, # P2300R10 std::execution
"headers": ["execution"],
"unimplemented": True,
},
{
"name": "__cpp_lib_shared_mutex",
"values": {"c++17": 201505},
Expand Down
1 change: 1 addition & 0 deletions libcxx/utils/libcxx/header_information.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
"flat_set",
"generator",
"hazard_pointer",
"inplace_vector",
"linalg",
"rcu",
"spanstream",
Expand Down
10 changes: 8 additions & 2 deletions lld/MachO/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1725,7 +1725,10 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella,
}

// Initialize symbols.
exportingFile = isImplicitlyLinked(installName) ? this : this->umbrella;
bool canBeImplicitlyLinked = findCommand(hdr, LC_SUB_CLIENT) == nullptr;
exportingFile = (canBeImplicitlyLinked && isImplicitlyLinked(installName))
? this
: this->umbrella;

const auto *dyldInfo = findCommand<dyld_info_command>(hdr, LC_DYLD_INFO_ONLY);
const auto *exportsTrie =
Expand Down Expand Up @@ -1884,7 +1887,10 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella,

checkAppExtensionSafety(interface.isApplicationExtensionSafe());

exportingFile = isImplicitlyLinked(installName) ? this : umbrella;
bool canBeImplicitlyLinked = interface.allowableClients().size() == 0;
exportingFile = (canBeImplicitlyLinked && isImplicitlyLinked(installName))
? this
: umbrella;
auto addSymbol = [&](const llvm::MachO::Symbol &symbol,
const Twine &name) -> void {
StringRef savedName = saver().save(name);
Expand Down
48 changes: 48 additions & 0 deletions lld/test/MachO/implicit-and-allowable-clients.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# REQUIRES: aarch64
# RUN: rm -rf %t; split-file %s %t
# RUN: ln -s Versions/A/FrameworkPublic.tbd %t/System/Library/Frameworks/FrameworkPublic.framework/
# RUN: ln -s Versions/A/FrameworkPrivate.tbd %t/System/Library/Frameworks/FrameworkPrivate.framework/
# RUN: llvm-mc -filetype obj -triple arm64-apple-macos11.0 %t/test.s -o %t/test.o
# RUN: %lld -arch arm64 -platform_version macos 11.0 11.0 -o %t/test -syslibroot %t -framework FrameworkPublic %t/test.o

# RUN: llvm-objdump --bind --no-show-raw-insn -d %t/test | FileCheck %s
# CHECK: Bind table:
# CHECK-DAG: __DATA __data {{.*}} pointer 0 FrameworkPublic _funcPublic
# CHECK-DAG: __DATA __data {{.*}} pointer 0 FrameworkPublic _funcPrivate

#--- System/Library/Frameworks/FrameworkPublic.framework/Versions/A/FrameworkPublic.tbd
--- !tapi-tbd
tbd-version: 4
targets: [ arm64-macos ]
install-name: '/System/Library/Frameworks/FrameworkPublic.framework/Versions/A/FrameworkPublic'
current-version: 1.0.0
reexported-libraries:
- targets: [ arm64-macos ]
libraries: [ '/System/Library/Frameworks/FrameworkPrivate.framework/Versions/A/FrameworkPrivate' ]
exports:
- targets: [ arm64-macos ]
symbols: [ '_funcPublic' ]
...
#--- System/Library/Frameworks/FrameworkPrivate.framework/Versions/A/FrameworkPrivate.tbd
--- !tapi-tbd
tbd-version: 4
targets: [ arm64-macos ]
install-name: '/System/Library/Frameworks/FrameworkPrivate.framework/Versions/A/FrameworkPrivate'
current-version: 1.0.0
allowable-clients:
- targets: [ arm64-macos ]
clients: [ FrameworkPublic ]
exports:
- targets: [ arm64-macos ]
symbols: [ '_funcPrivate' ]
...
#--- test.s
.text
.globl _main

_main:
ret

.data
.quad _funcPublic
.quad _funcPrivate
1 change: 1 addition & 0 deletions lldb/include/lldb/Symbol/ObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>,
lldb::offset_t file_offset,
lldb::offset_t file_size,
lldb_private::ModuleSpecList &specs);
static bool IsObjectFile(lldb_private::FileSpec file_spec);
/// Split a path into a file path with object name.
///
/// For paths like "/tmp/foo.a(bar.o)" we often need to split a path up into
Expand Down
150 changes: 41 additions & 109 deletions lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,31 @@
#include "lldb/Utility/Stream.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include <cstdint>
#include <locale>
#include <optional>

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;

// The flattened layout of the std::__tree_iterator::__ptr_ looks
// as follows:
//
// The following shows the contiguous block of memory:
//
// +-----------------------------+ class __tree_end_node
// __ptr_ | pointer __left_; |
// +-----------------------------+ class __tree_node_base
// | pointer __right_; |
// | __parent_pointer __parent_; |
// | bool __is_black_; |
// +-----------------------------+ class __tree_node
// | __node_value_type __value_; | <<< our key/value pair
// +-----------------------------+
//
// where __ptr_ has type __iter_pointer.

class MapEntry {
public:
MapEntry() = default;
Expand Down Expand Up @@ -182,10 +202,6 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
size_t GetIndexOfChildWithName(ConstString name) override;

private:
bool GetDataType();

void GetValueOffset(const lldb::ValueObjectSP &node);

/// Returns the ValueObject for the __tree_node type that
/// holds the key/value pair of the node at index \ref idx.
///
Expand All @@ -204,8 +220,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {

ValueObject *m_tree = nullptr;
ValueObject *m_root_node = nullptr;
CompilerType m_element_type;
uint32_t m_skip_size = UINT32_MAX;
CompilerType m_node_ptr_type;
size_t m_count = UINT32_MAX;
std::map<size_t, MapIterator> m_iterators;
};
Expand Down Expand Up @@ -234,7 +249,7 @@ class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {

lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::
LibcxxStdMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
: SyntheticChildrenFrontEnd(*valobj_sp), m_element_type(), m_iterators() {
: SyntheticChildrenFrontEnd(*valobj_sp) {
if (valobj_sp)
Update();
}
Expand All @@ -260,130 +275,44 @@ llvm::Expected<uint32_t> lldb_private::formatters::
return m_count;
}

bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() {
if (m_element_type.IsValid())
return true;
m_element_type.Clear();
ValueObjectSP deref;
Status error;
deref = m_root_node->Dereference(error);
if (!deref || error.Fail())
return false;
deref = m_backend.GetChildAtNamePath({"__tree_", "__pair3_"});
if (!deref)
return false;
m_element_type = deref->GetCompilerType()
.GetTypeTemplateArgument(1)
.GetTypeTemplateArgument(1);
if (m_element_type) {
std::string name;
uint64_t bit_offset_ptr;
uint32_t bitfield_bit_size_ptr;
bool is_bitfield_ptr;
m_element_type = m_element_type.GetFieldAtIndex(
0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
m_element_type = m_element_type.GetTypedefedType();
return m_element_type.IsValid();
} else {
m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0);
return m_element_type.IsValid();
}
}

void lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset(
const lldb::ValueObjectSP &node) {
if (m_skip_size != UINT32_MAX)
return;
if (!node)
return;

CompilerType node_type(node->GetCompilerType());
auto ast_ctx = node_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
if (!ast_ctx)
return;

CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
llvm::StringRef(),
{{"ptr0", ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
{"ptr1", ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
{"ptr2", ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
{"cw", ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
{"payload", (m_element_type.GetCompleteType(), m_element_type)}});
std::string child_name;
uint32_t child_byte_size;
int32_t child_byte_offset = 0;
uint32_t child_bitfield_bit_size;
uint32_t child_bitfield_bit_offset;
bool child_is_base_class;
bool child_is_deref_of_parent;
uint64_t language_flags;
auto child_type =
llvm::expectedToStdOptional(tree_node_type.GetChildCompilerTypeAtIndex(
nullptr, 4, true, true, true, child_name, child_byte_size,
child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
child_is_base_class, child_is_deref_of_parent, nullptr,
language_flags));
if (child_type && child_type->IsValid())
m_skip_size = (uint32_t)child_byte_offset;
}

ValueObjectSP
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetKeyValuePair(
size_t idx, size_t max_depth) {
MapIterator iterator(m_root_node, max_depth);

const bool need_to_skip = (idx > 0);
size_t actual_advance = idx;
if (need_to_skip) {
size_t advance_by = idx;
if (idx > 0) {
// If we have already created the iterator for the previous
// index, we can start from there and advance by 1.
auto cached_iterator = m_iterators.find(idx - 1);
if (cached_iterator != m_iterators.end()) {
iterator = cached_iterator->second;
actual_advance = 1;
advance_by = 1;
}
}

ValueObjectSP iterated_sp(iterator.advance(actual_advance));
ValueObjectSP iterated_sp(iterator.advance(advance_by));
if (!iterated_sp)
// this tree is garbage - stop
return nullptr;

if (!GetDataType())
if (!m_node_ptr_type.IsValid())
return nullptr;

if (!need_to_skip) {
Status error;
iterated_sp = iterated_sp->Dereference(error);
if (!iterated_sp || error.Fail())
return nullptr;

GetValueOffset(iterated_sp);
iterated_sp = iterated_sp->GetSyntheticChildAtOffset(m_skip_size,
m_element_type, true);

if (!iterated_sp)
return nullptr;
} else {
// because of the way our debug info is made, we need to read item 0
// first so that we can cache information used to generate other elements
if (m_skip_size == UINT32_MAX)
GetChildAtIndex(0);

if (m_skip_size == UINT32_MAX)
return nullptr;

iterated_sp = iterated_sp->GetSyntheticChildAtOffset(m_skip_size,
m_element_type, true);
if (!iterated_sp)
return nullptr;
}
// iterated_sp is a __iter_pointer at this point.
// We can cast it to a __node_pointer (which is what libc++ does).
auto value_type_sp = iterated_sp->Cast(m_node_ptr_type);
if (!value_type_sp)
return nullptr;

// Finally, get the key/value pair.
value_type_sp = value_type_sp->GetChildMemberWithName("__value_");
if (!value_type_sp)
return nullptr;

m_iterators[idx] = iterator;
assert(iterated_sp != nullptr &&
"Cached MapIterator for invalid ValueObject");

return iterated_sp;
return value_type_sp;
}

lldb::ValueObjectSP
Expand Down Expand Up @@ -443,6 +372,9 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::Update() {
if (!m_tree)
return lldb::ChildCacheState::eRefetch;
m_root_node = m_tree->GetChildMemberWithName("__begin_node_").get();
m_node_ptr_type =
m_tree->GetCompilerType().GetDirectNestedTypeWithName("__node_pointer");

return lldb::ChildCacheState::eRefetch;
}

Expand Down
9 changes: 9 additions & 0 deletions lldb/source/Symbol/ObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@ ObjectFileSP ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp,
return object_file_sp;
}

bool ObjectFile::IsObjectFile(lldb_private::FileSpec file_spec) {
DataBufferSP data_sp;
offset_t data_offset = 0;
ModuleSP module_sp = std::make_shared<Module>(file_spec);
return static_cast<bool>(ObjectFile::FindPlugin(
module_sp, &file_spec, 0, FileSystem::Instance().GetByteSize(file_spec),
data_sp, data_offset));
}

size_t ObjectFile::GetModuleSpecifications(const FileSpec &file,
lldb::offset_t file_offset,
lldb::offset_t file_size,
Expand Down
87 changes: 44 additions & 43 deletions lldb/source/Target/Platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,6 @@ Status
Platform::ResolveExecutable(const ModuleSpec &module_spec,
lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr) {
Status error;

// We may connect to a process and use the provided executable (Don't use
// local $PATH).
Expand All @@ -741,55 +740,57 @@ Platform::ResolveExecutable(const ModuleSpec &module_spec,
// Resolve any executable within a bundle on MacOSX
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());

if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()) ||
module_spec.GetUUID().IsValid()) {
if (resolved_module_spec.GetArchitecture().IsValid() ||
resolved_module_spec.GetUUID().IsValid()) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
module_search_paths_ptr, nullptr,
nullptr);
if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()) &&
!module_spec.GetUUID().IsValid())
return Status::createWithFormat("'{0}' does not exist",
resolved_module_spec.GetFileSpec());

if (resolved_module_spec.GetArchitecture().IsValid() ||
resolved_module_spec.GetUUID().IsValid()) {
Status error =
ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
module_search_paths_ptr, nullptr, nullptr);

if (exe_module_sp && exe_module_sp->GetObjectFile())
return error;
exe_module_sp.reset();
}
// No valid architecture was specified or the exact arch wasn't found.
// Ask the platform for the architectures that we should be using (in the
// correct order) and see if we can find a match that way.
StreamString arch_names;
llvm::ListSeparator LS;
ArchSpec process_host_arch;
Status error;
for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {
resolved_module_spec.GetArchitecture() = arch;
error =
ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
module_search_paths_ptr, nullptr, nullptr);
if (error.Success()) {
if (exe_module_sp && exe_module_sp->GetObjectFile())
return error;
exe_module_sp.reset();
break;
error.SetErrorToGenericError();
}
// No valid architecture was specified or the exact arch wasn't found.
// Ask the platform for the architectures that we should be using (in the
// correct order) and see if we can find a match that way.
StreamString arch_names;
llvm::ListSeparator LS;
ArchSpec process_host_arch;
for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {
resolved_module_spec.GetArchitecture() = arch;
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
module_search_paths_ptr, nullptr,
nullptr);
if (error.Success()) {
if (exe_module_sp && exe_module_sp->GetObjectFile())
break;
error.SetErrorToGenericError();
}

arch_names << LS << arch.GetArchitectureName();
}
arch_names << LS << arch.GetArchitectureName();
}

if (error.Fail() || !exe_module_sp) {
if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
error.SetErrorStringWithFormatv(
"'{0}' doesn't contain any '{1}' platform architectures: {2}",
resolved_module_spec.GetFileSpec(), GetPluginName(),
arch_names.GetData());
} else {
error.SetErrorStringWithFormatv("'{0}' is not readable",
resolved_module_spec.GetFileSpec());
}
}
} else {
error.SetErrorStringWithFormatv("'{0}' does not exist",
if (exe_module_sp && error.Success())
return {};

if (!FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec()))
return Status::createWithFormat("'{0}' is not readable",
resolved_module_spec.GetFileSpec());
}

return error;
if (!ObjectFile::IsObjectFile(resolved_module_spec.GetFileSpec()))
return Status::createWithFormat("'{0}' is not a valid executable",
resolved_module_spec.GetFileSpec());

return Status::createWithFormat(
"'{0}' doesn't contain any '{1}' platform architectures: {2}",
resolved_module_spec.GetFileSpec(), GetPluginName(),
arch_names.GetData());
}

Status Platform::ResolveSymbolFile(Target &target, const ModuleSpec &sym_spec,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# RUN: yaml2obj %s -o %t.exe
# RUN: %lldb %t.exe 2>&1 | FileCheck %s

# CHECK: error: '{{.*}}' doesn't contain any {{.*}} platform architectures
# CHECK: error: '{{.*}}' is not a valid executable
--- !COFF
OptionalHeader:
AddressOfEntryPoint: 4096
Expand Down
4 changes: 4 additions & 0 deletions llvm/docs/CommandGuide/llvm-objcopy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,10 @@ them.
Allow :program:`llvm-objcopy` to remove sections even if it would leave invalid
section references. Any invalid sh_link fields will be set to zero.

.. option:: --change-section-lma \*{+-}<val>

Shift LMA of non-zero-sized segments by ``<val>``.

.. option:: --change-start <incr>, --adjust-start

Add ``<incr>`` to the program's start address. Can be specified multiple
Expand Down
9 changes: 9 additions & 0 deletions llvm/include/llvm/BinaryFormat/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "llvm/ADT/StringRef.h"
#include <cstdint>
#include <cstring>
#include <type_traits>

namespace llvm {
namespace ELF {
Expand Down Expand Up @@ -1430,6 +1431,14 @@ struct Elf64_Rela {
}
};

// In-memory representation of CREL. The serialized representation uses LEB128.
template <bool Is64> struct Elf_Crel {
std::conditional_t<Is64, uint64_t, uint32_t> r_offset;
uint32_t r_symidx;
uint32_t r_type;
std::conditional_t<Is64, int64_t, int32_t> r_addend;
};

// Relocation entry without explicit addend or info (relative relocations only).
typedef Elf64_Xword Elf64_Relr; // offset/bitmap for relative relocations

Expand Down
63 changes: 63 additions & 0 deletions llvm/include/llvm/MC/MCELFExtras.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//===- MCELFExtras.h - Extra functions for ELF ------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_MC_MCELFEXTRAS_H
#define LLVM_MC_MCELFEXTRAS_H

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/bit.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/raw_ostream.h"

#include <cstdint>
#include <type_traits>

namespace llvm::ELF {
// Encode relocations as CREL to OS. ToCrel is responsible for converting a
// const RelocsTy & to an Elf_Crel.
template <bool Is64, class RelocsTy, class F>
void encodeCrel(raw_ostream &OS, RelocsTy Relocs, F ToCrel) {
using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
uint OffsetMask = 8, Offset = 0, Addend = 0;
uint32_t SymIdx = 0, Type = 0;
for (const auto &R : Relocs)
OffsetMask |= ToCrel(R).r_offset;
const int Shift = llvm::countr_zero(OffsetMask);
encodeULEB128(Relocs.size() * 8 + ELF::CREL_HDR_ADDEND + Shift, OS);
for (const auto &R : Relocs) {
auto CR = ToCrel(R);
auto DeltaOffset = static_cast<uint>((CR.r_offset - Offset) >> Shift);
Offset = CR.r_offset;
uint8_t B = (DeltaOffset << 3) + (SymIdx != CR.r_symidx) +
(Type != CR.r_type ? 2 : 0) +
(Addend != uint(CR.r_addend) ? 4 : 0);
if (DeltaOffset < 0x10) {
OS << char(B);
} else {
OS << char(B | 0x80);
encodeULEB128(DeltaOffset >> 4, OS);
}
// Delta symidx/type/addend members (SLEB128).
if (B & 1) {
encodeSLEB128(static_cast<int32_t>(CR.r_symidx - SymIdx), OS);
SymIdx = CR.r_symidx;
}
if (B & 2) {
encodeSLEB128(static_cast<int32_t>(CR.r_type - Type), OS);
Type = CR.r_type;
}
if (B & 4) {
encodeSLEB128(std::make_signed_t<uint>(CR.r_addend - Addend), OS);
Addend = CR.r_addend;
}
}
}
} // namespace llvm::ELF

#endif
3 changes: 3 additions & 0 deletions llvm/include/llvm/ObjCopy/CommonConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ struct CommonConfig {
// Symbol info specified by --add-symbol option.
SmallVector<NewSymbolInfo, 0> SymbolsToAdd;

// Integer options
int64_t ChangeSectionLMAValAll = 0;

// Boolean options
bool DeterministicArchives = true;
bool ExtractDWO = false;
Expand Down
43 changes: 43 additions & 0 deletions llvm/include/llvm/Object/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Object/ELFTypes.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Error.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <type_traits>
#include <utility>

namespace llvm {
Expand Down Expand Up @@ -207,6 +209,47 @@ bool isSectionInSegment(const typename ELFT::Phdr &Phdr,
checkSectionVMA<ELFT>(Phdr, Sec);
}

// HdrHandler is called once with the number of relocations and whether the
// relocations have addends. EntryHandler is called once per decoded relocation.
template <bool Is64>
Error decodeCrel(
ArrayRef<uint8_t> Content,
function_ref<void(uint64_t /*relocation count*/, bool /*explicit addends*/)>
HdrHandler,
function_ref<void(Elf_Crel_Impl<Is64>)> EntryHandler) {
DataExtractor Data(Content, true, 8); // endian and address size are unused
DataExtractor::Cursor Cur(0);
const uint64_t Hdr = Data.getULEB128(Cur);
size_t Count = Hdr / 8;
const size_t FlagBits = Hdr & ELF::CREL_HDR_ADDEND ? 3 : 2;
const size_t Shift = Hdr % ELF::CREL_HDR_ADDEND;
using uint = typename Elf_Crel_Impl<Is64>::uint;
uint Offset = 0, Addend = 0;
HdrHandler(Count, Hdr & ELF::CREL_HDR_ADDEND);
uint32_t SymIdx = 0, Type = 0;
for (; Count; --Count) {
// The delta offset and flags member may be larger than uint64_t. Special
// case the first byte (2 or 3 flag bits; the rest are offset bits). Other
// ULEB128 bytes encode the remaining delta offset bits.
const uint8_t B = Data.getU8(Cur);
Offset += B >> FlagBits;
if (B >= 0x80)
Offset += (Data.getULEB128(Cur) << (7 - FlagBits)) - (0x80 >> FlagBits);
// Delta symidx/type/addend members (SLEB128).
if (B & 1)
SymIdx += Data.getSLEB128(Cur);
if (B & 2)
Type += Data.getSLEB128(Cur);
if (B & 4 & Hdr)
Addend += Data.getSLEB128(Cur);
if (!Cur)
break;
EntryHandler(
{Offset << Shift, SymIdx, Type, std::make_signed_t<uint>(Addend)});
}
return Cur.takeError();
}

template <class ELFT>
class ELFFile {
public:
Expand Down
69 changes: 63 additions & 6 deletions llvm/include/llvm/Object/ELFObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "llvm/Support/ELFAttributes.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/TargetParser/SubtargetFeature.h"
Expand Down Expand Up @@ -122,6 +123,8 @@ class ELFObjectFileBase : public ObjectFile {
Expected<std::vector<BBAddrMap>>
readBBAddrMap(std::optional<unsigned> TextSectionIndex = std::nullopt,
std::vector<PGOAnalysisMap> *PGOAnalyses = nullptr) const;

StringRef getCrelDecodeProblem(SectionRef Sec) const;
};

class ELFSectionRef : public SectionRef {
Expand Down Expand Up @@ -292,6 +295,10 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section.
const Elf_Shdr *DotSymtabShndxSec = nullptr; // SHT_SYMTAB_SHNDX section.

// Hold CREL relocations for SectionRef::relocations().
mutable SmallVector<SmallVector<Elf_Crel, 0>, 0> Crels;
mutable SmallVector<std::string, 0> CrelDecodeProblems;

Error initContent() override;

void moveSymbolNext(DataRefImpl &Symb) const override;
Expand Down Expand Up @@ -446,6 +453,7 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {

const Elf_Rel *getRel(DataRefImpl Rel) const;
const Elf_Rela *getRela(DataRefImpl Rela) const;
Elf_Crel getCrel(DataRefImpl Crel) const;

Expected<const Elf_Sym *> getSymbol(DataRefImpl Sym) const {
return EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b);
Expand Down Expand Up @@ -499,6 +507,8 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
bool isRelocatableObject() const override;

void createFakeSections() { EF.createFakeSections(); }

StringRef getCrelDecodeProblem(DataRefImpl Sec) const;
};

using ELF32LEObjectFile = ELFObjectFile<ELF32LE>;
Expand Down Expand Up @@ -1022,6 +1032,24 @@ ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const {
uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin());
RelData.d.a = (Sec.p - SHT) / EF.getHeader().e_shentsize;
RelData.d.b = 0;
if (reinterpret_cast<const Elf_Shdr *>(Sec.p)->sh_type == ELF::SHT_CREL) {
if (RelData.d.a + 1 > Crels.size())
Crels.resize(RelData.d.a + 1);
auto &Crel = Crels[RelData.d.a];
if (Crel.empty()) {
ArrayRef<uint8_t> Content = cantFail(getSectionContents(Sec));
size_t I = 0;
Error Err = decodeCrel<ELFT::Is64Bits>(
Content, [&](uint64_t Count, bool) { Crel.resize(Count); },
[&](Elf_Crel Crel) { Crels[RelData.d.a][I++] = Crel; });
if (Err) {
Crel.assign(1, Elf_Crel{0, 0, 0, 0});
if (RelData.d.a + 1 > CrelDecodeProblems.size())
CrelDecodeProblems.resize(RelData.d.a + 1);
CrelDecodeProblems[RelData.d.a] = toString(std::move(Err));
}
}
}
return relocation_iterator(RelocationRef(RelData, this));
}

Expand All @@ -1030,9 +1058,13 @@ relocation_iterator
ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const {
const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p);
relocation_iterator Begin = section_rel_begin(Sec);
DataRefImpl RelData = Begin->getRawDataRefImpl();
if (S->sh_type == ELF::SHT_CREL) {
RelData.d.b = Crels[RelData.d.a].size();
return relocation_iterator(RelocationRef(RelData, this));
}
if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL)
return Begin;
DataRefImpl RelData = Begin->getRawDataRefImpl();
const Elf_Shdr *RelSec = getRelSection(RelData);

// Error check sh_link here so that getRelocationSymbol can just use it.
Expand All @@ -1050,7 +1082,7 @@ Expected<section_iterator>
ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
const Elf_Shdr *EShdr = getSection(Sec);
uintX_t Type = EShdr->sh_type;
if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA)
if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA && Type != ELF::SHT_CREL)
return section_end();

Expected<const Elf_Shdr *> SecOrErr = EF.getSection(EShdr->sh_info);
Expand All @@ -1070,7 +1102,9 @@ symbol_iterator
ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
uint32_t symbolIdx;
const Elf_Shdr *sec = getRelSection(Rel);
if (sec->sh_type == ELF::SHT_REL)
if (sec->sh_type == ELF::SHT_CREL)
symbolIdx = getCrel(Rel).r_symidx;
else if (sec->sh_type == ELF::SHT_REL)
symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL());
else
symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL());
Expand All @@ -1087,6 +1121,8 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const {
const Elf_Shdr *sec = getRelSection(Rel);
if (sec->sh_type == ELF::SHT_CREL)
return getCrel(Rel).r_offset;
if (sec->sh_type == ELF::SHT_REL)
return getRel(Rel)->r_offset;

Expand All @@ -1096,6 +1132,8 @@ uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const {
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel) const {
const Elf_Shdr *sec = getRelSection(Rel);
if (sec->sh_type == ELF::SHT_CREL)
return getCrel(Rel).r_type;
if (sec->sh_type == ELF::SHT_REL)
return getRel(Rel)->getType(EF.isMips64EL());
else
Expand All @@ -1117,9 +1155,11 @@ void ELFObjectFile<ELFT>::getRelocationTypeName(
template <class ELFT>
Expected<int64_t>
ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel) const {
if (getRelSection(Rel)->sh_type != ELF::SHT_RELA)
return createError("Section is not SHT_RELA");
return (int64_t)getRela(Rel)->r_addend;
if (getRelSection(Rel)->sh_type == ELF::SHT_RELA)
return (int64_t)getRela(Rel)->r_addend;
if (getRelSection(Rel)->sh_type == ELF::SHT_CREL)
return (int64_t)getCrel(Rel).r_addend;
return createError("Relocation section does not have addends");
}

template <class ELFT>
Expand All @@ -1142,6 +1182,14 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const {
return *Ret;
}

template <class ELFT>
typename ELFObjectFile<ELFT>::Elf_Crel
ELFObjectFile<ELFT>::getCrel(DataRefImpl Crel) const {
assert(getRelSection(Crel)->sh_type == ELF::SHT_CREL);
assert(Crel.d.a < Crels.size());
return Crels[Crel.d.a][Crel.d.b];
}

template <class ELFT>
Expected<ELFObjectFile<ELFT>>
ELFObjectFile<ELFT>::create(MemoryBufferRef Object, bool InitContent) {
Expand Down Expand Up @@ -1453,6 +1501,15 @@ template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const {
return EF.getHeader().e_type == ELF::ET_REL;
}

template <class ELFT>
StringRef ELFObjectFile<ELFT>::getCrelDecodeProblem(DataRefImpl Sec) const {
uintptr_t SHT = reinterpret_cast<uintptr_t>(cantFail(EF.sections()).begin());
auto I = (Sec.p - SHT) / EF.getHeader().e_shentsize;
if (I < CrelDecodeProblems.size())
return CrelDecodeProblems[I];
return "";
}

} // end namespace object
} // end namespace llvm

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,12 @@ class LoopVectorizationLegality {
bool canVectorizeFPMath(bool EnableStrictReductions);

/// Return true if we can vectorize this loop while folding its tail by
/// masking, and mark all respective loads/stores for masking.
/// This object's state is only modified iff this function returns true.
bool prepareToFoldTailByMasking();
/// masking.
bool canFoldTailByMasking() const;

/// Mark all respective loads/stores for masking. Must only be called when
/// tail-folding is possible.
void prepareToFoldTailByMasking();

/// Returns the primary induction variable.
PHINode *getPrimaryInduction() { return PrimaryInduction; }
Expand Down
49 changes: 10 additions & 39 deletions llvm/lib/MC/ELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELFExtras.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
Expand Down Expand Up @@ -903,44 +904,14 @@ void ELFWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
WriteWord(EntrySize); // sh_entsize
}

template <class uint>
template <bool Is64>
static void encodeCrel(ArrayRef<ELFRelocationEntry> Relocs, raw_ostream &OS) {
uint OffsetMask = 8, Offset = 0, Addend = 0;
uint32_t SymIdx = 0, Type = 0;
// hdr & 4 indicates 3 flag bits in delta offset and flags members.
for (const ELFRelocationEntry &Entry : Relocs)
OffsetMask |= Entry.Offset;
const int Shift = llvm::countr_zero(OffsetMask);
encodeULEB128(Relocs.size() * 8 + ELF::CREL_HDR_ADDEND + Shift, OS);
for (const ELFRelocationEntry &Entry : Relocs) {
// The delta offset and flags member may be larger than uint64_t. Special
// case the first byte (3 flag bits and 4 offset bits). Other ULEB128 bytes
// encode the remaining delta offset bits.
auto DeltaOffset = static_cast<uint>((Entry.Offset - Offset) >> Shift);
Offset = Entry.Offset;
uint32_t CurSymIdx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
uint8_t B = (DeltaOffset << 3) + (SymIdx != CurSymIdx) +
(Type != Entry.Type ? 2 : 0) + (Addend != Entry.Addend ? 4 : 0);
if (DeltaOffset < 0x10) {
OS << char(B);
} else {
OS << char(B | 0x80);
encodeULEB128(DeltaOffset >> 4, OS);
}
// Delta symidx/type/addend members (SLEB128).
if (B & 1) {
encodeSLEB128(static_cast<int32_t>(CurSymIdx - SymIdx), OS);
SymIdx = CurSymIdx;
}
if (B & 2) {
encodeSLEB128(static_cast<int32_t>(Entry.Type - Type), OS);
Type = Entry.Type;
}
if (B & 4) {
encodeSLEB128(std::make_signed_t<uint>(Entry.Addend - Addend), OS);
Addend = Entry.Addend;
}
}
using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
ELF::encodeCrel<Is64>(OS, Relocs, [&](const ELFRelocationEntry &R) {
uint32_t SymIdx = R.Symbol ? R.Symbol->getIndex() : 0;
return ELF::Elf_Crel<Is64>{static_cast<uint>(R.Offset), SymIdx, R.Type,
std::make_signed_t<uint>(R.Addend)};
});
}

void ELFWriter::writeRelocations(const MCAssembler &Asm,
Expand Down Expand Up @@ -989,9 +960,9 @@ void ELFWriter::writeRelocations(const MCAssembler &Asm,
}
} else if (TO && TO->Crel) {
if (is64Bit())
encodeCrel<uint64_t>(Relocs, W.OS);
encodeCrel<true>(Relocs, W.OS);
else
encodeCrel<uint32_t>(Relocs, W.OS);
encodeCrel<false>(Relocs, W.OS);
} else {
for (const ELFRelocationEntry &Entry : Relocs) {
uint32_t Symidx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
Expand Down
11 changes: 7 additions & 4 deletions llvm/lib/ObjCopy/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
Common.StripNonAlloc || Common.StripSections || Common.Weaken ||
Common.DecompressDebugSections ||
Common.DiscardMode == DiscardType::Locals ||
!Common.SymbolsToAdd.empty() || Common.GapFill != 0 || Common.PadTo != 0)
!Common.SymbolsToAdd.empty() || Common.GapFill != 0 ||
Common.PadTo != 0 || Common.ChangeSectionLMAValAll != 0)
return createStringError(llvm::errc::invalid_argument,
"option is not supported for COFF");

Expand All @@ -46,7 +47,8 @@ Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
Common.StripNonAlloc || Common.StripSections ||
Common.DecompressDebugSections || Common.StripUnneeded ||
Common.DiscardMode == DiscardType::Locals ||
!Common.SymbolsToAdd.empty() || Common.GapFill != 0 || Common.PadTo != 0)
!Common.SymbolsToAdd.empty() || Common.GapFill != 0 ||
Common.PadTo != 0 || Common.ChangeSectionLMAValAll != 0)
return createStringError(llvm::errc::invalid_argument,
"option is not supported for MachO");

Expand All @@ -66,7 +68,7 @@ Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
!Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
!Common.SetSectionFlags.empty() || !Common.SetSectionType.empty() ||
!Common.SymbolsToRename.empty() || Common.GapFill != 0 ||
Common.PadTo != 0)
Common.PadTo != 0 || Common.ChangeSectionLMAValAll != 0)
return createStringError(llvm::errc::invalid_argument,
"only flags for section dumping, removal, and "
"addition are supported");
Expand Down Expand Up @@ -94,7 +96,8 @@ Expected<const XCOFFConfig &> ConfigManager::getXCOFFConfig() const {
Common.PreserveDates || Common.StripAllGNU || Common.StripDWO ||
Common.StripDebug || Common.StripNonAlloc || Common.StripSections ||
Common.Weaken || Common.StripUnneeded || Common.DecompressDebugSections ||
Common.GapFill != 0 || Common.PadTo != 0) {
Common.GapFill != 0 || Common.PadTo != 0 ||
Common.ChangeSectionLMAValAll != 0) {
return createStringError(
llvm::errc::invalid_argument,
"no flags are supported yet, only basic copying is allowed");
Expand Down
27 changes: 27 additions & 0 deletions llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,33 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
}
}

if (Config.ChangeSectionLMAValAll != 0) {
for (Segment &Seg : Obj.segments()) {
if (Seg.FileSize > 0) {
if (Config.ChangeSectionLMAValAll > 0 &&
Seg.PAddr > std::numeric_limits<uint64_t>::max() -
Config.ChangeSectionLMAValAll) {
return createStringError(
errc::invalid_argument,
"address 0x" + Twine::utohexstr(Seg.PAddr) +
" cannot be increased by 0x" +
Twine::utohexstr(Config.ChangeSectionLMAValAll) +
". The result would overflow");
} else if (Config.ChangeSectionLMAValAll < 0 &&
Seg.PAddr < std::numeric_limits<uint64_t>::min() -
Config.ChangeSectionLMAValAll) {
return createStringError(
errc::invalid_argument,
"address 0x" + Twine::utohexstr(Seg.PAddr) +
" cannot be decreased by 0x" +
Twine::utohexstr(std::abs(Config.ChangeSectionLMAValAll)) +
". The result would underflow");
}
Seg.PAddr += Config.ChangeSectionLMAValAll;
}
}
}

if (Config.OnlyKeepDebug)
for (auto &Sec : Obj.sections())
if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
Expand Down
58 changes: 50 additions & 8 deletions llvm/lib/ObjCopy/ELF/ELFObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCELFExtras.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFObjectFile.h"
Expand Down Expand Up @@ -107,12 +108,29 @@ Error ELFSectionSizer<ELFT>::visit(SymbolTableSection &Sec) {
return Error::success();
}

template <bool Is64>
static SmallVector<char, 0> encodeCrel(ArrayRef<Relocation> Relocations) {
using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
SmallVector<char, 0> Content;
raw_svector_ostream OS(Content);
ELF::encodeCrel<Is64>(OS, Relocations, [&](const Relocation &R) {
uint32_t CurSymIdx = R.RelocSymbol ? R.RelocSymbol->Index : 0;
return ELF::Elf_Crel<Is64>{static_cast<uint>(R.Offset), CurSymIdx, R.Type,
std::make_signed_t<uint>(R.Addend)};
});
return Content;
}

template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(RelocationSection &Sec) {
Sec.EntrySize = Sec.Type == SHT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela);
Sec.Size = Sec.Relocations.size() * Sec.EntrySize;
// Align to the largest field in Elf_Rel(a).
Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
if (Sec.Type == SHT_CREL) {
Sec.Size = encodeCrel<ELFT::Is64Bits>(Sec.Relocations).size();
} else {
Sec.EntrySize = Sec.Type == SHT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela);
Sec.Size = Sec.Relocations.size() * Sec.EntrySize;
// Align to the largest field in Elf_Rel(a).
Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
}
return Error::success();
}

Expand Down Expand Up @@ -874,6 +892,8 @@ StringRef RelocationSectionBase::getNamePrefix() const {
return ".rel";
case SHT_RELA:
return ".rela";
case SHT_CREL:
return ".crel";
default:
llvm_unreachable("not a relocation section");
}
Expand Down Expand Up @@ -966,12 +986,16 @@ static void writeRel(const RelRange &Relocations, T *Buf, bool IsMips64EL) {
template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) {
uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
if (Sec.Type == SHT_REL)
if (Sec.Type == SHT_CREL) {
auto Content = encodeCrel<ELFT::Is64Bits>(Sec.Relocations);
memcpy(Buf, Content.data(), Content.size());
} else if (Sec.Type == SHT_REL) {
writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf),
Sec.getObject().IsMips64EL);
else
} else {
writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf),
Sec.getObject().IsMips64EL);
}
return Error::success();
}

Expand Down Expand Up @@ -1684,6 +1708,7 @@ Expected<SectionBase &> ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {
switch (Shdr.sh_type) {
case SHT_REL:
case SHT_RELA:
case SHT_CREL:
if (Shdr.sh_flags & SHF_ALLOC) {
if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
return Obj.addSection<DynamicRelocationSection>(*Data);
Expand Down Expand Up @@ -1861,7 +1886,15 @@ template <class ELFT> Error ELFBuilder<ELFT>::readSections(bool EnsureSymtab) {

const typename ELFFile<ELFT>::Elf_Shdr *Shdr =
Sections->begin() + RelSec->Index;
if (RelSec->Type == SHT_REL) {
if (RelSec->Type == SHT_CREL) {
auto RelsOrRelas = ElfFile.crels(*Shdr);
if (!RelsOrRelas)
return RelsOrRelas.takeError();
if (Error Err = initRelocations(RelSec, RelsOrRelas->first))
return Err;
if (Error Err = initRelocations(RelSec, RelsOrRelas->second))
return Err;
} else if (RelSec->Type == SHT_REL) {
Expected<typename ELFFile<ELFT>::Elf_Rel_Range> Rels =
ElfFile.rels(*Shdr);
if (!Rels)
Expand Down Expand Up @@ -2206,8 +2239,17 @@ Error Object::removeSections(
// Transfer removed sections into the Object RemovedSections container for use
// later.
std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
// Now finally get rid of them all together.
// Now get rid of them altogether.
Sections.erase(Iter, std::end(Sections));

// Finally erase empty SHT_GROUP sections.
llvm::erase_if(Sections, [](const SecPtr &Sec) {
if (auto GroupSec = dyn_cast<GroupSection>(Sec.get()))
return GroupSec->getMembersCount() == 0;

return false;
});

return Error::success();
}

Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/ObjCopy/ELF/ELFObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,8 @@ class RelocationSectionBase : public SectionBase {
StringRef getNamePrefix() const;

static bool classof(const SectionBase *S) {
return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
return is_contained({ELF::SHT_REL, ELF::SHT_RELA, ELF::SHT_CREL},
S->OriginalType);
}
};

Expand Down Expand Up @@ -925,7 +926,7 @@ class RelocationSection
static bool classof(const SectionBase *S) {
if (S->OriginalFlags & ELF::SHF_ALLOC)
return false;
return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
return RelocationSectionBase::classof(S);
}
};

Expand Down Expand Up @@ -963,6 +964,8 @@ class GroupSection : public SectionBase {
const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
void onRemove() override;

size_t getMembersCount() const { return GroupMembers.size(); }

static bool classof(const SectionBase *S) {
return S->OriginalType == ELF::SHT_GROUP;
}
Expand Down
61 changes: 23 additions & 38 deletions llvm/lib/Object/ELF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,46 +408,31 @@ ELFFile<ELFT>::getCrelHeader(ArrayRef<uint8_t> Content) const {
template <class ELFT>
Expected<typename ELFFile<ELFT>::RelsOrRelas>
ELFFile<ELFT>::decodeCrel(ArrayRef<uint8_t> Content) const {
DataExtractor Data(Content, isLE(), sizeof(typename ELFT::Addr));
DataExtractor::Cursor Cur(0);
const uint64_t Hdr = Data.getULEB128(Cur);
const size_t Count = Hdr / 8;
const size_t FlagBits = Hdr & ELF::CREL_HDR_ADDEND ? 3 : 2;
const size_t Shift = Hdr % ELF::CREL_HDR_ADDEND;
std::vector<Elf_Rel> Rels;
std::vector<Elf_Rela> Relas;
if (Hdr & ELF::CREL_HDR_ADDEND)
Relas.resize(Count);
else
Rels.resize(Count);
typename ELFT::uint Offset = 0, Addend = 0;
uint32_t SymIdx = 0, Type = 0;
for (size_t I = 0; I != Count; ++I) {
// The delta offset and flags member may be larger than uint64_t. Special
// case the first byte (2 or 3 flag bits; the rest are offset bits). Other
// ULEB128 bytes encode the remaining delta offset bits.
const uint8_t B = Data.getU8(Cur);
Offset += B >> FlagBits;
if (B >= 0x80)
Offset += (Data.getULEB128(Cur) << (7 - FlagBits)) - (0x80 >> FlagBits);
// Delta symidx/type/addend members (SLEB128).
if (B & 1)
SymIdx += Data.getSLEB128(Cur);
if (B & 2)
Type += Data.getSLEB128(Cur);
if (B & 4 & Hdr)
Addend += Data.getSLEB128(Cur);
if (Hdr & ELF::CREL_HDR_ADDEND) {
Relas[I].r_offset = Offset << Shift;
Relas[I].setSymbolAndType(SymIdx, Type, false);
Relas[I].r_addend = Addend;
} else {
Rels[I].r_offset = Offset << Shift;
Rels[I].setSymbolAndType(SymIdx, Type, false);
}
}
if (!Cur)
return std::move(Cur.takeError());
size_t I = 0;
bool HasAddend;
Error Err = object::decodeCrel<ELFT::Is64Bits>(
Content,
[&](uint64_t Count, bool HasA) {
HasAddend = HasA;
if (HasAddend)
Relas.resize(Count);
else
Rels.resize(Count);
},
[&](Elf_Crel Crel) {
if (HasAddend) {
Relas[I].r_offset = Crel.r_offset;
Relas[I].setSymbolAndType(Crel.r_symidx, Crel.r_type, false);
Relas[I++].r_addend = Crel.r_addend;
} else {
Rels[I].r_offset = Crel.r_offset;
Rels[I++].setSymbolAndType(Crel.r_symidx, Crel.r_type, false);
}
});
if (Err)
return std::move(Err);
return std::make_pair(std::move(Rels), std::move(Relas));
}

Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Object/ELFObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1013,3 +1013,14 @@ Expected<std::vector<BBAddrMap>> ELFObjectFileBase::readBBAddrMap(
return readBBAddrMapImpl(cast<ELF64BEObjectFile>(this)->getELFFile(),
TextSectionIndex, PGOAnalyses);
}

StringRef ELFObjectFileBase::getCrelDecodeProblem(SectionRef Sec) const {
auto Data = Sec.getRawDataRefImpl();
if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(this))
return Obj->getCrelDecodeProblem(Data);
if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(this))
return Obj->getCrelDecodeProblem(Data);
if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(this))
return Obj->getCrelDecodeProblem(Data);
return cast<ELF64BEObjectFile>(this)->getCrelDecodeProblem(Data);
}
66 changes: 66 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3905,6 +3905,65 @@ static SDValue lowerBuildVectorOfConstants(SDValue Op, SelectionDAG &DAG,
return SDValue();
}

/// Double the element size of the build vector to reduce the number
/// of vslide1down in the build vector chain. In the worst case, this
/// trades three scalar operations for 1 vector operation. Scalar
/// operations are generally lower latency, and for out-of-order cores
/// we also benefit from additional parallelism.
static SDValue lowerBuildVectorViaPacking(SDValue Op, SelectionDAG &DAG,
const RISCVSubtarget &Subtarget) {
SDLoc DL(Op);
MVT VT = Op.getSimpleValueType();
assert(VT.isFixedLengthVector() && "Unexpected vector!");
MVT ElemVT = VT.getVectorElementType();
if (!ElemVT.isInteger())
return SDValue();

// TODO: Relax these architectural restrictions, possibly with costing
// of the actual instructions required.
if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
return SDValue();

unsigned NumElts = VT.getVectorNumElements();
unsigned ElemSizeInBits = ElemVT.getSizeInBits();
if (ElemSizeInBits >= std::min(Subtarget.getELen(), Subtarget.getXLen()) ||
NumElts % 2 != 0)
return SDValue();

// Produce [B,A] packed into a type twice as wide. Note that all
// scalars are XLenVT, possibly masked (see below).
MVT XLenVT = Subtarget.getXLenVT();
auto pack = [&](SDValue A, SDValue B) {
// Bias the scheduling of the inserted operations to near the
// definition of the element - this tends to reduce register
// pressure overall.
SDLoc ElemDL(B);
SDValue ShtAmt = DAG.getConstant(ElemSizeInBits, ElemDL, XLenVT);
return DAG.getNode(ISD::OR, ElemDL, XLenVT, A,
DAG.getNode(ISD::SHL, ElemDL, XLenVT, B, ShtAmt));
};

SDValue Mask = DAG.getConstant(
APInt::getLowBitsSet(XLenVT.getSizeInBits(), ElemSizeInBits), DL, XLenVT);
SmallVector<SDValue> NewOperands;
NewOperands.reserve(NumElts / 2);
for (unsigned i = 0; i < VT.getVectorNumElements(); i += 2) {
SDValue A = Op.getOperand(i);
SDValue B = Op.getOperand(i + 1);
// Bias the scheduling of the inserted operations to near the
// definition of the element - this tends to reduce register
// pressure overall.
A = DAG.getNode(ISD::AND, SDLoc(A), XLenVT, A, Mask);
B = DAG.getNode(ISD::AND, SDLoc(B), XLenVT, B, Mask);
NewOperands.push_back(pack(A, B));
}
assert(NumElts == NewOperands.size() * 2);
MVT WideVT = MVT::getIntegerVT(ElemSizeInBits * 2);
MVT WideVecVT = MVT::getVectorVT(WideVT, NumElts / 2);
return DAG.getNode(ISD::BITCAST, DL, VT,
DAG.getBuildVector(WideVecVT, DL, NewOperands));
}

// Convert to an vXf16 build_vector to vXi16 with bitcasts.
static SDValue lowerBUILD_VECTORvXf16(SDValue Op, SelectionDAG &DAG) {
MVT VT = Op.getSimpleValueType();
Expand Down Expand Up @@ -4006,6 +4065,13 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
return convertFromScalableVector(VT, Vec, DAG, Subtarget);
}

// If we're about to resort to vslide1down (or stack usage), pack our
// elements into the widest scalar type we can. This will force a VL/VTYPE
// toggle, but reduces the critical path, the number of vslide1down ops
// required, and possibly enables scalar folds of the values.
if (SDValue Res = lowerBuildVectorViaPacking(Op, DAG, Subtarget))
return Res;

// For m1 vectors, if we have non-undef values in both halves of our vector,
// split the vector into low and high halves, build them separately, then
// use a vselect to combine them. For long vectors, this cuts the critical
Expand Down
32 changes: 15 additions & 17 deletions llvm/lib/TargetParser/Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -703,14 +703,13 @@ static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
}
}

static StringRef
getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
const unsigned *Features,
unsigned *Type, unsigned *Subtype) {
auto testFeature = [&](unsigned F) {
return (Features[F / 32] & (1U << (F % 32))) != 0;
};
#define testFeature(F) (Features[F / 32] & (1 << (F % 32))) != 0

static StringRef getIntelProcessorTypeAndSubtype(unsigned Family,
unsigned Model,
const unsigned *Features,
unsigned *Type,
unsigned *Subtype) {
StringRef CPU;

switch (Family) {
Expand Down Expand Up @@ -1067,15 +1066,12 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
return CPU;
}

static StringRef
getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
const unsigned *Features,
unsigned *Type, unsigned *Subtype) {
auto testFeature = [&](unsigned F) {
return (Features[F / 32] & (1U << (F % 32))) != 0;
};

StringRef CPU;
static const char *getAMDProcessorTypeAndSubtype(unsigned Family,
unsigned Model,
const unsigned *Features,
unsigned *Type,
unsigned *Subtype) {
const char *CPU = 0;

switch (Family) {
case 4:
Expand Down Expand Up @@ -1215,14 +1211,16 @@ getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
*Subtype = X86::AMDFAM19H_ZNVER4;
break; // "znver4"
}
break;
break; // family 19h
default:
break; // Unknown AMD CPU.
}

return CPU;
}

#undef testFeature

static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
unsigned *Features) {
unsigned EAX, EBX;
Expand Down
32 changes: 22 additions & 10 deletions llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/CaptureTracking.h"
Expand Down Expand Up @@ -130,7 +131,7 @@ class SanitizerBinaryMetadata {
std::unique_ptr<SpecialCaseList> Ignorelist)
: Mod(M), Options(transformOptionsFromCl(std::move(Opts))),
Ignorelist(std::move(Ignorelist)), TargetTriple(M.getTargetTriple()),
IRB(M.getContext()) {
VersionStr(utostr(getVersion())), IRB(M.getContext()) {
// FIXME: Make it work with other formats.
assert(TargetTriple.isOSBinFormatELF() && "ELF only");
assert(!(TargetTriple.isNVPTX() || TargetTriple.isAMDGPU()) &&
Expand Down Expand Up @@ -167,10 +168,10 @@ class SanitizerBinaryMetadata {
StringRef getSectionName(StringRef SectionSuffix);

// Returns the section start marker name.
Twine getSectionStart(StringRef SectionSuffix);
StringRef getSectionStart(StringRef SectionSuffix);

// Returns the section end marker name.
Twine getSectionEnd(StringRef SectionSuffix);
StringRef getSectionEnd(StringRef SectionSuffix);

// Returns true if the access to the address should be considered "atomic".
bool pretendAtomicAccess(const Value *Addr);
Expand All @@ -179,6 +180,7 @@ class SanitizerBinaryMetadata {
const SanitizerBinaryMetadataOptions Options;
std::unique_ptr<SpecialCaseList> Ignorelist;
const Triple TargetTriple;
const std::string VersionStr;
IRBuilder<> IRB;
BumpPtrAllocator Alloc;
UniqueStringSaver StringPool{Alloc};
Expand Down Expand Up @@ -209,19 +211,25 @@ bool SanitizerBinaryMetadata::run() {
getSectionMarker(getSectionStart(MI->SectionSuffix), PtrTy),
getSectionMarker(getSectionEnd(MI->SectionSuffix), PtrTy),
};

// Calls to the initialization functions with different versions cannot be
// merged. Give the structors unique names based on the version, which will
// also be used as the COMDAT key.
const std::string StructorPrefix = (MI->FunctionPrefix + VersionStr).str();

// We declare the _add and _del functions as weak, and only call them if
// there is a valid symbol linked. This allows building binaries with
// semantic metadata, but without having callbacks. When a tool that wants
// the metadata is linked which provides the callbacks, they will be called.
Function *Ctor =
createSanitizerCtorAndInitFunctions(
Mod, (MI->FunctionPrefix + ".module_ctor").str(),
Mod, StructorPrefix + ".module_ctor",
(MI->FunctionPrefix + "_add").str(), InitTypes, InitArgs,
/*VersionCheckName=*/StringRef(), /*Weak=*/ClWeakCallbacks)
.first;
Function *Dtor =
createSanitizerCtorAndInitFunctions(
Mod, (MI->FunctionPrefix + ".module_dtor").str(),
Mod, StructorPrefix + ".module_dtor",
(MI->FunctionPrefix + "_del").str(), InitTypes, InitArgs,
/*VersionCheckName=*/StringRef(), /*Weak=*/ClWeakCallbacks)
.first;
Expand Down Expand Up @@ -454,15 +462,19 @@ SanitizerBinaryMetadata::getSectionMarker(const Twine &MarkerName, Type *Ty) {
StringRef SanitizerBinaryMetadata::getSectionName(StringRef SectionSuffix) {
// FIXME: Other TargetTriples.
// Request ULEB128 encoding for all integer constants.
return StringPool.save(SectionSuffix + "!C");
return StringPool.save(SectionSuffix + VersionStr + "!C");
}

Twine SanitizerBinaryMetadata::getSectionStart(StringRef SectionSuffix) {
return "__start_" + SectionSuffix;
StringRef SanitizerBinaryMetadata::getSectionStart(StringRef SectionSuffix) {
// Twine only concatenates 2 strings; with >2 strings, concatenating them
// creates Twine temporaries, and returning the final Twine no longer works
// because we'd end up with a stack-use-after-return. So here we also use the
// StringPool to store the new string.
return StringPool.save("__start_" + SectionSuffix + VersionStr);
}

Twine SanitizerBinaryMetadata::getSectionEnd(StringRef SectionSuffix) {
return "__stop_" + SectionSuffix;
StringRef SanitizerBinaryMetadata::getSectionEnd(StringRef SectionSuffix) {
return StringPool.save("__stop_" + SectionSuffix + VersionStr);
}

} // namespace
Expand Down
Loading