llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-libcxx Author: Mark de Wever (mordante) <details> <summary>Changes</summary> __format_to_n_buffer is not used in the public library interface so the changes are not an ABI break. Before Benchmark Time CPU Time Old Time New CPU Old CPU New ---------------------------------------------------------------------------------------------------------------------------------------------------------------- BM_format_to_n_string_back_inserter<std::string>/1 -0.0160 -0.0136 59 58 59 58 BM_format_to_n_string_back_inserter<std::string>/2 +0.0020 +0.0044 58 59 58 59 BM_format_to_n_string_back_inserter<std::string>/4 +0.0084 +0.0109 58 59 58 59 BM_format_to_n_string_back_inserter<std::string>/8 -0.0014 +0.0014 59 59 58 59 BM_format_to_n_string_back_inserter<std::string>/16 -0.0042 -0.0018 59 58 59 58 BM_format_to_n_string_back_inserter<std::string>/32 -0.0136 -0.0112 78 77 78 77 BM_format_to_n_string_back_inserter<std::string>/64 -0.0096 -0.0072 78 77 77 77 BM_format_to_n_string_back_inserter<std::string>/128 -0.1486 -0.1465 91 77 91 77 BM_format_to_n_string_back_inserter<std::string>/256 -0.1215 -0.1191 102 90 102 90 BM_format_to_n_string_back_inserter<std::string>/512 -0.1412 -0.1391 158 136 158 136 BM_format_to_n_string_back_inserter<std::string>/1024 -0.1135 -0.1114 290 257 289 257 BM_format_to_n_string_back_inserter<std::string>/2048 -0.1551 -0.1530 489 413 488 413 BM_format_to_n_string_back_inserter<std::string>/4096 -0.1665 -0.1642 801 668 799 668 BM_format_to_n_string_back_inserter<std::string>/8192 -0.2301 -0.2282 1449 1116 1445 1116 BM_format_to_n_string_back_inserter<std::string>/16384 -0.1988 -0.1965 2942 2357 2933 2357 BM_format_to_n_string_back_inserter<std::string>/32768 -0.2129 -0.2109 5676 4467 5661 4467 BM_format_to_n_string_back_inserter<std::string>/65536 -0.2469 -0.2449 12437 9366 12404 9366 BM_format_to_n_string_back_inserter<std::string>/131072 -0.2294 -0.2274 25855 19923 25787 19923 BM_format_to_n_string_back_inserter<std::string>/262144 -0.1906 -0.1885 52880 42798 52739 42798 BM_format_to_n_string_back_inserter<std::string>/524288 -0.1898 -0.1876 107703 87261 107410 87257 BM_format_to_n_string_back_inserter<std::string>/1048576 -0.2162 -0.2139 231479 181427 230781 181426 BM_format_to_n_string_back_inserter<std::vector<char>>/1 -0.0035 -0.0007 72 72 72 72 BM_format_to_n_string_back_inserter<std::vector<char>>/2 +0.0104 +0.0128 73 73 72 73 BM_format_to_n_string_back_inserter<std::vector<char>>/4 -0.0022 +0.0003 74 74 74 74 BM_format_to_n_string_back_inserter<std::vector<char>>/8 +0.0092 +0.0116 75 76 75 76 BM_format_to_n_string_back_inserter<std::vector<char>>/16 -0.0019 +0.0005 79 79 79 79 BM_format_to_n_string_back_inserter<std::vector<char>>/32 +0.0168 +0.0195 89 90 88 90 BM_format_to_n_string_back_inserter<std::vector<char>>/64 -0.0077 -0.0054 91 90 90 90 BM_format_to_n_string_back_inserter<std::vector<char>>/128 -0.1628 -0.1608 109 91 109 91 BM_format_to_n_string_back_inserter<std::vector<char>>/256 -0.0994 -0.0971 120 108 119 108 BM_format_to_n_string_back_inserter<std::vector<char>>/512 -0.1116 -0.1095 186 165 186 165 BM_format_to_n_string_back_inserter<std::vector<char>>/1024 -0.1168 -0.1144 284 250 283 250 BM_format_to_n_string_back_inserter<std::vector<char>>/2048 -0.1664 -0.1644 484 404 483 404 BM_format_to_n_string_back_inserter<std::vector<char>>/4096 -0.2161 -0.2143 802 629 800 629 BM_format_to_n_string_back_inserter<std::vector<char>>/8192 -0.2834 -0.2817 1469 1053 1466 1053 BM_format_to_n_string_back_inserter<std::vector<char>>/16384 -0.2365 -0.2344 2700 2062 2693 2062 BM_format_to_n_string_back_inserter<std::vector<char>>/32768 -0.2359 -0.2341 4979 3805 4967 3805 BM_format_to_n_string_back_inserter<std::vector<char>>/65536 -0.2754 -0.2736 10431 7558 10405 7558 BM_format_to_n_string_back_inserter<std::vector<char>>/131072 -0.2505 -0.2487 22646 16973 22591 16973 BM_format_to_n_string_back_inserter<std::vector<char>>/262144 -0.1981 -0.1958 46278 37110 46148 37111 BM_format_to_n_string_back_inserter<std::vector<char>>/524288 -0.2027 -0.2011 91695 73110 91511 73108 BM_format_to_n_string_back_inserter<std::vector<char>>/1048576 -0.2367 -0.2348 195458 149194 194988 149197 BM_format_to_n_string_back_inserter<std::list<char>>/1 +0.0045 +0.0068 66 66 65 66 BM_format_to_n_string_back_inserter<std::list<char>>/2 +0.0068 +0.0092 79 79 79 79 BM_format_to_n_string_back_inserter<std::list<char>>/4 -0.0026 +0.0001 107 107 107 107 BM_format_to_n_string_back_inserter<std::list<char>>/8 +0.0498 +0.0523 171 180 171 180 BM_format_to_n_string_back_inserter<std::list<char>>/16 +0.0100 +0.0124 331 334 330 334 BM_format_to_n_string_back_inserter<std::list<char>>/32 +0.0320 +0.0345 641 662 640 662 BM_format_to_n_string_back_inserter<std::list<char>>/64 +0.0242 +0.0270 1237 1267 1233 1267 BM_format_to_n_string_back_inserter<std::list<char>>/128 +0.0025 +0.0047 2474 2480 2469 2480 BM_format_to_n_string_back_inserter<std::list<char>>/256 -0.0122 -0.0098 4984 4923 4972 4924 BM_format_to_n_string_back_inserter<std::list<char>>/512 +0.0074 +0.0098 9740 9812 9716 9811 BM_format_to_n_string_back_inserter<std::list<char>>/1024 +0.0045 +0.0072 19503 19590 19451 19591 BM_format_to_n_string_back_inserter<std::list<char>>/2048 +0.0021 +0.0046 39078 39161 38981 39159 BM_format_to_n_string_back_inserter<std::list<char>>/4096 -0.0002 +0.0023 78329 78316 78132 78315 BM_format_to_n_string_back_inserter<std::list<char>>/8192 +0.0001 +0.0026 156689 156709 156291 156699 BM_format_to_n_string_back_inserter<std::list<char>>/16384 -0.0025 +0.0004 313624 312842 312732 312842 BM_format_to_n_string_back_inserter<std::list<char>>/32768 -0.0009 +0.0017 630336 629744 628711 629751 BM_format_to_n_string_back_inserter<std::list<char>>/65536 -0.0029 -0.0001 1261542 1257851 1258055 1257872 BM_format_to_n_string_back_inserter<std::list<char>>/131072 -0.0047 -0.0016 2543001 2531022 2535000 2530835 BM_format_to_n_string_back_inserter<std::list<char>>/262144 -0.0061 -0.0017 5214390 5182786 5191608 5182661 BM_format_to_n_string_back_inserter<std::list<char>>/524288 -0.0079 -0.0040 10650366 10566644 10609616 10566709 BM_format_to_n_string_back_inserter<std::list<char>>/1048576 -0.0165 -0.0108 21677130 21319849 21550764 21318080 BM_format_to_n_string_begin<std::string>/1 -0.0931 -0.0909 54 49 54 49 BM_format_to_n_string_begin<std::string>/2 -0.0861 -0.0839 53 48 53 48 BM_format_to_n_string_begin<std::string>/4 -0.0872 -0.0847 53 49 53 49 BM_format_to_n_string_begin<std::string>/8 -0.0963 -0.0939 54 48 54 48 BM_format_to_n_string_begin<std::string>/16 -0.0969 -0.0947 54 48 54 48 BM_format_to_n_string_begin<std::string>/32 -0.1108 -0.1086 54 48 54 48 BM_format_to_n_string_begin<std::string>/64 -0.1107 -0.1086 54 48 54 48 BM_format_to_n_string_begin<std::string>/128 -0.2054 -0.2036 61 48 61 48 BM_format_to_n_string_begin<std::string>/256 -0.2768 -0.2751 69 50 69 50 BM_format_to_n_string_begin<std::string>/512 -0.4127 -0.4112 90 53 89 53 BM_format_to_n_string_begin<std::string>/1024 -0.5743 -0.5734 132 56 132 56 BM_format_to_n_string_begin<std::string>/2048 -0.7063 -0.7056 229 67 228 67 BM_format_to_n_string_begin<std::string>/4096 -0.7617 -0.7611 425 101 424 101 BM_format_to_n_string_begin<std::string>/8192 -0.8153 -0.8148 812 150 810 150 BM_format_to_n_string_begin<std::string>/16384 -0.8140 -0.8136 1656 308 1652 308 BM_format_to_n_string_begin<std::string>/32768 -0.5789 -0.5779 3179 1339 3171 1339 BM_format_to_n_string_begin<std::string>/65536 -0.5170 -0.5158 6818 3293 6802 3293 BM_format_to_n_string_begin<std::string>/131072 -0.5552 -0.5539 14829 6596 14788 6596 BM_format_to_n_string_begin<std::string>/262144 -0.5240 -0.5228 29547 14064 29471 14065 BM_format_to_n_string_begin<std::string>/524288 -0.5049 -0.5036 59436 29428 59284 29428 BM_format_to_n_string_begin<std::string>/1048576 -0.5123 -0.5110 120292 58666 119974 58666 BM_format_to_n_string_begin<std::vector<char>>/1 -0.0947 -0.0925 53 48 53 48 BM_format_to_n_string_begin<std::vector<char>>/2 -0.0859 -0.0834 53 48 53 48 BM_format_to_n_string_begin<std::vector<char>>/4 -0.0913 -0.0892 53 48 53 48 BM_format_to_n_string_begin<std::vector<char>>/8 -0.0808 -0.0786 52 48 52 48 BM_format_to_n_string_begin<std::vector<char>>/16 -0.0808 -0.0786 53 48 53 48 BM_format_to_n_string_begin<std::vector<char>>/32 -0.0921 -0.0899 53 48 53 48 BM_format_to_n_string_begin<std::vector<char>>/64 -0.0918 -0.0897 53 48 53 48 BM_format_to_n_string_begin<std::vector<char>>/128 -0.1769 -0.1747 59 48 59 48 BM_format_to_n_string_begin<std::vector<char>>/256 -0.3249 -0.3233 73 49 73 49 BM_format_to_n_string_begin<std::vector<char>>/512 -0.4552 -0.4539 97 53 96 53 BM_format_to_n_string_begin<std::vector<char>>/1024 -0.5978 -0.5969 138 56 138 56 BM_format_to_n_string_begin<std::vector<char>>/2048 -0.7152 -0.7144 235 67 235 67 BM_format_to_n_string_begin<std::vector<char>>/4096 -0.7780 -0.7775 439 98 438 98 BM_format_to_n_string_begin<std::vector<char>>/8192 -0.8230 -0.8226 853 151 851 151 BM_format_to_n_string_begin<std::vector<char>>/16384 -0.8065 -0.8060 1627 315 1623 315 BM_format_to_n_string_begin<std::vector<char>>/32768 -0.5823 -0.5811 3221 1345 3212 1345 BM_format_to_n_string_begin<std::vector<char>>/65536 -0.5351 -0.5340 7089 3295 7072 3295 BM_format_to_n_string_begin<std::vector<char>>/131072 -0.5683 -0.5672 15268 6591 15229 6590 BM_format_to_n_string_begin<std::vector<char>>/262144 -0.5351 -0.5339 30296 14084 30219 14084 BM_format_to_n_string_begin<std::vector<char>>/524288 -0.5061 -0.5049 61230 30239 61074 30238 BM_format_to_n_string_begin<std::vector<char>>/1048576 -0.5143 -0.5128 124101 60270 123704 60271 BM_format_to_n_string_begin<std::list<char>>/1 +0.0383 +0.0408 49 51 49 51 BM_format_to_n_string_begin<std::list<char>>/2 +0.0278 +0.0301 50 51 50 51 BM_format_to_n_string_begin<std::list<char>>/4 +0.0388 +0.0412 51 53 51 53 BM_format_to_n_string_begin<std::list<char>>/8 -0.0386 -0.0360 64 62 64 62 BM_format_to_n_string_begin<std::list<char>>/16 -0.0225 -0.0201 85 83 85 83 BM_format_to_n_string_begin<std::list<char>>/32 -0.0095 -0.0071 127 126 127 126 BM_format_to_n_string_begin<std::list<char>>/64 -0.0072 -0.0048 214 212 213 212 BM_format_to_n_string_begin<std::list<char>>/128 -0.0117 -0.0092 389 385 388 385 BM_format_to_n_string_begin<std::list<char>>/256 -0.0034 -0.0009 749 746 747 746 BM_format_to_n_string_begin<std::list<char>>/512 -0.0098 -0.0074 1453 1439 1449 1439 BM_format_to_n_string_begin<std::list<char>>/1024 +0.0109 +0.0132 2852 2883 2845 2882 BM_format_to_n_string_begin<std::list<char>>/2048 +0.0088 +0.0113 5685 5735 5671 5735 BM_format_to_n_string_begin<std::list<char>>/4096 +0.0043 +0.0068 11312 11360 11283 11360 BM_format_to_n_string_begin<std::list<char>>/8192 +0.0171 +0.0197 22644 23030 22586 23030 BM_format_to_n_string_begin<std::list<char>>/16384 +0.0146 +0.0172 45298 45959 45180 45958 BM_format_to_n_string_begin<std::list<char>>/32768 +0.0167 +0.0195 90351 91864 90110 91864 BM_format_to_n_string_begin<std::list<char>>/65536 +0.0150 +0.0180 180594 183305 180048 183298 BM_format_to_n_string_begin<std::list<char>>/131072 +0.0060 +0.0092 373023 375274 371863 375279 BM_format_to_n_string_begin<std::list<char>>/262144 -0.0354 -0.0318 895166 863452 891717 863366 BM_format_to_n_string_begin<std::list<char>>/524288 -0.0745 -0.0712 2209006 2044442 2201104 2044356 BM_format_to_n_string_begin<std::list<char>>/1048576 -0.0161 -0.0125 4421130 4349820 4404315 4349352 BM_format_to_n_string_span<char>/1 -0.0987 -0.0965 53 48 53 48 BM_format_to_n_string_span<char>/2 -0.0768 -0.0745 53 48 52 48 BM_format_to_n_string_span<char>/4 -0.0904 -0.0882 53 48 53 48 BM_format_to_n_string_span<char>/8 -0.0868 -0.0846 53 48 53 48 BM_format_to_n_string_span<char>/16 -0.0957 -0.0932 54 49 54 49 BM_format_to_n_string_span<char>/32 -0.0926 -0.0904 53 48 53 48 BM_format_to_n_string_span<char>/64 -0.0923 -0.0876 53 48 53 48 BM_format_to_n_string_span<char>/128 -0.1998 -0.1977 61 49 61 49 BM_format_to_n_string_span<char>/256 -0.2900 -0.2883 69 49 69 49 BM_format_to_n_string_span<char>/512 -0.4116 -0.4100 90 53 89 53 BM_format_to_n_string_span<char>/1024 -0.5854 -0.5844 134 56 134 56 BM_format_to_n_string_span<char>/2048 -0.7000 -0.6993 223 67 222 67 BM_format_to_n_string_span<char>/4096 -0.7731 -0.7725 427 97 426 97 BM_format_to_n_string_span<char>/8192 -0.8164 -0.8159 818 150 816 150 BM_format_to_n_string_span<char>/16384 -0.3453 -0.3436 1622 1062 1617 1062 BM_format_to_n_string_span<char>/32768 -0.5885 -0.5875 3137 1291 3129 1291 BM_format_to_n_string_span<char>/65536 -0.5064 -0.5052 6698 3306 6682 3306 BM_format_to_n_string_span<char>/131072 -0.5622 -0.5612 14925 6534 14888 6534 BM_format_to_n_string_span<char>/262144 -0.5215 -0.5201 29688 14207 29603 14207 BM_format_to_n_string_span<char>/524288 -0.4899 -0.4888 59308 30252 59180 30253 BM_format_to_n_string_span<char>/1048576 -0.4927 -0.4913 118765 60247 118433 60248 BM_format_to_n_string_pointer<char>/1 -0.0827 -0.0804 52 48 52 48 BM_format_to_n_string_pointer<char>/2 -0.0843 -0.0821 53 48 53 48 BM_format_to_n_string_pointer<char>/4 -0.0944 -0.0920 53 48 53 48 BM_format_to_n_string_pointer<char>/8 -0.0875 -0.0853 53 48 53 48 BM_format_to_n_string_pointer<char>/16 -0.0793 -0.0771 53 48 53 48 BM_format_to_n_string_pointer<char>/32 -0.0767 -0.0743 52 48 52 48 BM_format_to_n_string_pointer<char>/64 -0.0935 -0.0914 53 48 53 48 BM_format_to_n_string_pointer<char>/128 -0.2203 -0.2182 62 49 62 49 BM_format_to_n_string_pointer<char>/256 -0.2950 -0.2933 70 49 69 49 BM_format_to_n_string_pointer<char>/512 -0.4038 -0.4025 88 53 88 53 BM_format_to_n_string_pointer<char>/1024 -0.5755 -0.5745 131 56 131 56 BM_format_to_n_string_pointer<char>/2048 -0.7043 -0.7036 226 67 225 67 BM_format_to_n_string_pointer<char>/4096 -0.7726 -0.7719 426 97 425 97 BM_format_to_n_string_pointer<char>/8192 -0.8157 -0.8153 815 150 813 150 BM_format_to_n_string_pointer<char>/16384 -0.3490 -0.3473 1618 1053 1614 1053 BM_format_to_n_string_pointer<char>/32768 -0.5880 -0.5870 3137 1293 3129 1292 BM_format_to_n_string_pointer<char>/65536 -0.5062 -0.5048 6693 3305 6675 3305 BM_format_to_n_string_pointer<char>/131072 -0.5617 -0.5606 14912 6536 14876 6536 BM_format_to_n_string_pointer<char>/262144 -0.5206 -0.5194 29685 14230 29609 14230 BM_format_to_n_string_pointer<char>/524288 -0.4884 -0.4873 59254 30316 59133 30315 BM_format_to_n_string_pointer<char>/1048576 -0.4924 -0.4915 118746 60274 118523 60275 --- Full diff: https://github.com/llvm/llvm-project/pull/101831.diff 8 Files Affected: - (modified) libcxx/include/__format/buffer.h (+115-111) - (modified) libcxx/test/libcxx/transitive_includes/cxx03.csv (+1) - (modified) libcxx/test/libcxx/transitive_includes/cxx11.csv (+1) - (modified) libcxx/test/libcxx/transitive_includes/cxx14.csv (+1) - (modified) libcxx/test/libcxx/transitive_includes/cxx17.csv (+1) - (modified) libcxx/test/libcxx/transitive_includes/cxx20.csv (+2) - (modified) libcxx/test/libcxx/transitive_includes/cxx23.csv (+2) - (modified) libcxx/test/libcxx/transitive_includes/cxx26.csv (+2) ``````````diff diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h index ccf79077dfa70..c41ea73b3eb7e 100644 --- a/libcxx/include/__format/buffer.h +++ b/libcxx/include/__format/buffer.h @@ -39,6 +39,7 @@ #include <__type_traits/conditional.h> #include <__utility/exception_guard.h> #include <__utility/move.h> +#include <climits> // LLVM-20 remove #include <cstddef> #include <stdexcept> #include <string_view> @@ -56,6 +57,30 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace __format { +// A helper to limit the total size of code units written. +class _LIBCPP_HIDE_FROM_ABI __max_output_size { +public: + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __max_output_size(size_t __max_size) : __max_size_{__max_size} {} + + // This function adjusts the size of a (bulk) write operations. It ensures the + // number of code units written by a __output_buffer never exceed + // __max_size_ code units. + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __write_request(size_t __code_units) { + size_t __result = + __code_units_written_ < __max_size_ ? std::min(__code_units, __max_size_ - __code_units_written_) : 0; + __code_units_written_ += __code_units; + return __result; + } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __code_units_written() const noexcept { return __code_units_written_; } + +private: + size_t __max_size_; + // The code units that would have been written if there was no limit. + // format_to_n returns this value. + size_t __code_units_written_{0}; +}; + /// A "buffer" that handles writing to the proper iterator. /// /// This helper is used together with the @ref back_insert_iterator to offer @@ -81,9 +106,6 @@ namespace __format { /// This class is ABI-tagged, still the new design does not change the size of /// objects of this class. /// -/// The new design contains information regarding format_to_n changes, these -/// will be implemented in follow-up patch. -/// /// The new design is the following. /// - There is an external object that connects the buffer to the output. /// - This buffer object: @@ -189,12 +211,21 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer { : __ptr_(__ptr), __capacity_(__capacity), __flush_([](_CharT* __p, size_t __n, void* __o) { static_cast<_Tp*>(__o)->__flush(__p, __n); }), - __obj_(__obj) {} + __data_{.__version_llvm_20__ = false, .__obj_ = reinterpret_cast<uintptr_t>(__obj) >> 1} {} // New LLVM-20 function. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, __prepare_write_type __prepare_write) - : __ptr_(__ptr), __capacity_(__capacity), __prepare_write_(__prepare_write), __obj_(nullptr) {} + : __output_buffer{__ptr, __capacity, __prepare_write, nullptr} {} + + // New LLVM-20 function. + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __output_buffer( + _CharT* __ptr, size_t __capacity, __prepare_write_type __prepare_write, __max_output_size* __max_output_size) + : __ptr_(__ptr), + __capacity_(__capacity), + __prepare_write_(__prepare_write), + __data_{.__version_llvm_20_ = true, .__max_output_size_ = reinterpret_cast<uintptr_t>(__max_output_size) >> 1} { + } // Deprecated LLVM-19 function. _LIBCPP_HIDE_FROM_ABI void __reset(_CharT* __ptr, size_t __capacity) { @@ -215,6 +246,10 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer { // Used in std::back_insert_iterator. _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { + if (__data_.__version_llvm_20_ && __data_.__max_output_size_ && + reinterpret_cast<__max_output_size*>(__data_.__max_output_size_ << 1)->__write_request(1) == 0) + return; + __ptr_[__size_++] = __c; // Profiling showed flushing after adding is more efficient than flushing @@ -241,6 +276,11 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer { // upper case. For integral these strings are short. // TODO FMT Look at the improvements above. size_t __n = __str.size(); + if (__data_.__version_llvm_20_ && __data_.__max_output_size_) { + __n = reinterpret_cast<__max_output_size*>(__data_.__max_output_size_ << 1)->__write_request(__n); + if (__n == 0) + return; + } __flush_on_overflow(__n); if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). @@ -273,6 +313,12 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer { _LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range"); size_t __n = static_cast<size_t>(__last - __first); + if (__data_.__version_llvm_20_ && __data_.__max_output_size_) { + __n = reinterpret_cast<__max_output_size*>(__data_.__max_output_size_ << 1)->__write_request(__n); + if (__n == 0) + return; + } + __flush_on_overflow(__n); if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). std::transform(__first, __last, std::addressof(__ptr_[__size_]), std::move(__operation)); @@ -295,6 +341,12 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer { /// A \c fill_n wrapper. _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { + if (__data_.__version_llvm_20_ && __data_.__max_output_size_) { + __n = reinterpret_cast<__max_output_size*>(__data_.__max_output_size_ << 1)->__write_request(__n); + if (__n == 0) + return; + } + __flush_on_overflow(__n); if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). std::fill_n(std::addressof(__ptr_[__size_]), __n, __value); @@ -315,9 +367,9 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer { } _LIBCPP_HIDE_FROM_ABI void __flush(size_t __size_hint) { - if (__obj_) { + if (!__data_.__version_llvm_20_) { // LLVM-19 code path - __flush_(__ptr_, __size_, __obj_); + __flush_(__ptr_, __size_, reinterpret_cast<void*>(__data_.__obj_ << 1)); __size_ = 0; } else { // LLVM-20 code path @@ -340,7 +392,20 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer { }; static_assert(sizeof(__flush_) == sizeof(__prepare_write_), "The union is an ABI break."); static_assert(alignof(decltype(__flush_)) == alignof(decltype(__prepare_write_)), "The union is an ABI break."); - void* __obj_; + // Note this code is quite ugly, but it can cleaned up once the LLVM-19 parts + // of the code are removed. + union { + struct { + uintptr_t __version_llvm_20__ : 1; + uintptr_t __obj_ : CHAR_BIT * sizeof(void*) - 1; + }; + struct { + uintptr_t __version_llvm_20_ : 1; + uintptr_t __max_output_size_ : CHAR_BIT * sizeof(__max_output_size*) - 1; + }; + } __data_; + static_assert(sizeof(__data_) == sizeof(void*), "The struct is an ABI break."); + static_assert(alignof(decltype(__data_)) == alignof(void*), "The struct is an ABI break."); /// Flushes the buffer when the output operation would overflow the buffer. /// @@ -560,105 +625,6 @@ class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer { size_t __size_{0}; }; -/// The base of a buffer that counts and limits the number of insertions. -template <class _OutIt, __fmt_char_type _CharT, bool> - requires(output_iterator<_OutIt, const _CharT&>) -struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base { - using _Size = iter_difference_t<_OutIt>; - -public: - _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size) - : __writer_(std::move(__out_it)), __max_size_(std::max(_Size(0), __max_size)) {} - - _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { - if (_Size(__size_) <= __max_size_) - __writer_.__flush(__ptr, std::min(_Size(__n), __max_size_ - __size_)); - __size_ += __n; - } - -protected: - __internal_storage<_CharT> __storage_; - __output_buffer<_CharT> __output_{__storage_.__begin(), __storage_.__buffer_size, this}; - typename __writer_selector<_OutIt, _CharT>::type __writer_; - - _Size __max_size_; - _Size __size_{0}; -}; - -/// The base of a buffer that counts and limits the number of insertions. -/// -/// This version is used when \c __enable_direct_output<_OutIt, _CharT> == true. -/// -/// This class limits the size available to the direct writer so it will not -/// exceed the maximum number of code units. -template <class _OutIt, __fmt_char_type _CharT> - requires(output_iterator<_OutIt, const _CharT&>) -class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base<_OutIt, _CharT, true> { - using _Size = iter_difference_t<_OutIt>; - -public: - _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size) - : __output_(std::__unwrap_iter(__out_it), __max_size, this), - __writer_(std::move(__out_it)), - __max_size_(__max_size) { - if (__max_size <= 0) [[unlikely]] - __output_.__reset(__storage_.__begin(), __storage_.__buffer_size); - } - - _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { - // A __flush to the direct writer happens in the following occasions: - // - The format function has written the maximum number of allowed code - // units. At this point it's no longer valid to write to this writer. So - // switch to the internal storage. This internal storage doesn't need to - // be written anywhere so the __flush for that storage writes no output. - // - Like above, but the next "mass write" operation would overflow the - // buffer. In that case the buffer is pre-emptively switched. The still - // valid code units will be written separately. - // - The format_to_n function is finished. In this case there's no need to - // switch the buffer, but for simplicity the buffers are still switched. - // When the __max_size <= 0 the constructor already switched the buffers. - if (__size_ == 0 && __ptr != __storage_.__begin()) { - __writer_.__flush(__ptr, __n); - __output_.__reset(__storage_.__begin(), __storage_.__buffer_size); - } else if (__size_ < __max_size_) { - // Copies a part of the internal buffer to the output up to n characters. - // See __output_buffer<_CharT>::__flush_on_overflow for more information. - _Size __s = std::min(_Size(__n), __max_size_ - __size_); - std::copy_n(__ptr, __s, __writer_.__out_it()); - __writer_.__flush(__ptr, __s); - } - - __size_ += __n; - } - -protected: - __internal_storage<_CharT> __storage_; - __output_buffer<_CharT> __output_; - __writer_direct<_OutIt, _CharT> __writer_; - - _Size __max_size_; - _Size __size_{0}; -}; - -/// The buffer that counts and limits the number of insertions. -template <class _OutIt, __fmt_char_type _CharT> - requires(output_iterator<_OutIt, const _CharT&>) -struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final - : public __format_to_n_buffer_base< _OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>> { - using _Base = __format_to_n_buffer_base<_OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>>; - using _Size = iter_difference_t<_OutIt>; - -public: - _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer(_OutIt __out_it, _Size __max_size) - : _Base(std::move(__out_it), __max_size) {} - _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return this->__output_.__make_output_iterator(); } - - _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && { - this->__output_.__flush(0); - return {std::move(this->__writer_).__out_it(), this->__size_}; - } -}; - // ***** ***** ***** LLVM-20 classes ***** ***** ***** // A dynamically growing buffer. @@ -668,8 +634,11 @@ class _LIBCPP_TEMPLATE_VIS __allocating_buffer : public __output_buffer<_CharT> __allocating_buffer(const __allocating_buffer&) = delete; __allocating_buffer& operator=(const __allocating_buffer&) = delete; - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __allocating_buffer() - : __output_buffer<_CharT>{__buffer_, __buffer_size_, __prepare_write} {} + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __allocating_buffer() : __allocating_buffer{nullptr} {} + + [[nodiscard]] + _LIBCPP_HIDE_FROM_ABI explicit __allocating_buffer(__max_output_size* __max_output_size) + : __output_buffer<_CharT>{__buffer_, __buffer_size_, __prepare_write, __max_output_size} {} _LIBCPP_HIDE_FROM_ABI ~__allocating_buffer() { if (__ptr_ != __buffer_) { @@ -690,6 +659,7 @@ class _LIBCPP_TEMPLATE_VIS __allocating_buffer : public __output_buffer<_CharT> // its capacity is exceeded a dynamic buffer will be allocated. static constexpr size_t __buffer_size_ = 256; _CharT __buffer_[__buffer_size_]; + _CharT* __ptr_{__buffer_}; _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) { @@ -729,7 +699,12 @@ template <class _OutIt, __fmt_char_type _CharT> class _LIBCPP_TEMPLATE_VIS __direct_iterator_buffer : public __output_buffer<_CharT> { public: [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it) - : __output_buffer<_CharT>{std::__unwrap_iter(__out_it), __buffer_size, __prepare_write}, __out_it_(__out_it) {} + : __direct_iterator_buffer{__out_it, nullptr} {} + + [[nodiscard]] + _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it, __max_output_size* __max_output_size) + : __output_buffer<_CharT>{std::__unwrap_iter(__out_it), __buffer_size, __prepare_write, __max_output_size}, + __out_it_(__out_it) {} [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { return __out_it_ + this->__size(); } @@ -753,7 +728,12 @@ template <class _OutIt, __fmt_char_type _CharT> class _LIBCPP_TEMPLATE_VIS __container_inserter_buffer : public __output_buffer<_CharT> { public: [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it) - : __output_buffer<_CharT>{__buffer_, __buffer_size, __prepare_write}, __container_{__out_it.__get_container()} {} + : __container_inserter_buffer{__out_it, nullptr} {} + + [[nodiscard]] + _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it, __max_output_size* __max_output_size) + : __output_buffer<_CharT>{__buffer_, __buffer_size, __prepare_write, __max_output_size}, + __container_{__out_it.__get_container()} {} [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && { __container_->insert(__container_->end(), __buffer_, __buffer_ + this->__size()); @@ -791,6 +771,9 @@ class _LIBCPP_TEMPLATE_VIS __iterator_buffer : public __allocating_buffer<_CharT [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it) : __allocating_buffer<_CharT>{}, __out_it_{std::move(__out_it)} {} + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it, __max_output_size* __max_output_size) + : __allocating_buffer<_CharT>{__max_output_size}, __out_it_{std::move(__out_it)} {} + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && { return std::ranges::copy(this->__view(), std::move(__out_it_)).out; } @@ -813,6 +796,27 @@ class _LIBCPP_TEMPLATE_VIS __buffer_selector { __iterator_buffer<_OutIt, _CharT>>>; }; +// A buffer that counts and limits the number of insertions. +template <class _OutIt, __fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer : private __buffer_selector<_OutIt, _CharT>::type { +public: + using _Base = __buffer_selector<_OutIt, _CharT>::type; + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_to_n_buffer(_OutIt __out_it, iter_difference_t<_OutIt> __n) + : _Base{std::move(__out_it), std::addressof(__max_output_size_)}, + __max_output_size_{__n < 0 ? size_t{0} : static_cast<size_t>(__n)} {} + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return _Base::__make_output_iterator(); } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && { + return {static_cast<_Base&&>(*this).__out_it(), + static_cast<iter_difference_t<_OutIt>>(__max_output_size_.__code_units_written())}; + } + +private: + __max_output_size __max_output_size_; +}; + // ***** ***** ***** LLVM-19 and LLVM-20 class ***** ***** ***** // A dynamically growing buffer intended to be used for retargeting a context. diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv index 622fced5ffa40..f6e7db17f413f 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -860,6 +860,7 @@ thread atomic thread cctype thread cerrno thread chrono +thread climits thread clocale thread compare thread cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv index 11c3c1322c406..752fea058e63b 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -867,6 +867,7 @@ thread atomic thread cctype thread cerrno thread chrono +thread climits thread clocale thread compare thread cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv index 666d5c3896467..010f7e2fb82e9 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -870,6 +870,7 @@ thread atomic thread cctype thread cerrno thread chrono +thread climits thread clocale thread compare thread cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv index 3a3aa5a894473..64c2db3eef6f9 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx17.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv @@ -881,6 +881,7 @@ thread atomic thread cctype thread cerrno thread chrono +thread climits thread clocale thread compare thread cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv index 982c2013e3417..a7ea7f8dddbea 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx20.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv @@ -276,6 +276,7 @@ filesystem version format array format cctype format cerrno +format climits format clocale format cmath format cstddef @@ -896,6 +897,7 @@ thread array thread atomic thread cctype thread cerrno +thread climits thread clocale thread compare thread cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv index 8ffb71d8b566b..a7310f20125b9 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx23.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv @@ -180,6 +180,7 @@ filesystem version format array format cctype format cerrno +format climits format clocale format cmath format cstddef @@ -616,6 +617,7 @@ thread array thread atomic thread cctype thread cerrno +thread climits thread clocale thread compare thread cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv index 8ffb71d8b566b..a7310f20125b9 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx26.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv @@ -180,6 +180,7 @@ filesystem version format array format cctype format cerrno +format climits format clocale format cmath format cstddef @@ -616,6 +617,7 @@ thread array thread atomic thread cctype thread cerrno +thread climits thread clocale thread compare thread cstddef `````````` </details> https://github.com/llvm/llvm-project/pull/101831 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits