[llvm-branch-commits] [libcxx] [libc++][format][5/7] Improve std::format_to_n (PR #101831)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Aug 3 08:20:24 PDT 2024
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
More information about the llvm-branch-commits
mailing list