[libc-commits] [libc] [libc] Add option to disable printf bit int (PR #180832)

via libc-commits libc-commits at lists.llvm.org
Tue Feb 10 12:58:13 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Michael Jones (michaelrj-google)

<details>
<summary>Changes</summary>

Requested as a binary size optinization. Updates the parser, converter
utils, config, tests, and docs.


---
Full diff: https://github.com/llvm/llvm-project/pull/180832.diff


12 Files Affected:

- (modified) libc/cmake/modules/LLVMLibCCompileOptionRules.cmake (+4) 
- (modified) libc/config/baremetal/config.json (+4-1) 
- (modified) libc/config/config.json (+4-1) 
- (modified) libc/docs/configure.rst (+1) 
- (modified) libc/docs/dev/printf_behavior.rst (+7-1) 
- (modified) libc/src/stdio/printf_core/converter_utils.h (+2) 
- (modified) libc/src/stdio/printf_core/core_structs.h (+15-1) 
- (modified) libc/src/stdio/printf_core/parser.h (+6) 
- (modified) libc/src/stdio/printf_core/write_int_converter.h (+2) 
- (modified) libc/test/UnitTest/PrintfMatcher.cpp (+2) 
- (modified) libc/test/src/stdio/printf_core/parser_test.cpp (+3) 
- (modified) libc/test/src/stdio/sprintf_test.cpp (+3) 


``````````diff
diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
index 98fc0206daa44..b15a9fab09c38 100644
--- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
+++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
@@ -151,6 +151,10 @@ function(_get_compile_options_from_config output_var)
     list(APPEND config_options "-DLIBC_COPT_PRINTF_DISABLE_WIDE")
   endif()
 
+  if(LIBC_COPT_PRINTF_DISABLE_BITINT)
+    list(APPEND config_options "-DLIBC_COPT_PRINTF_DISABLE_BITINT")
+  endif()
+
   set(${output_var} ${config_options} PARENT_SCOPE)
 endfunction(_get_compile_options_from_config)
 
diff --git a/libc/config/baremetal/config.json b/libc/config/baremetal/config.json
index af5b6115c87e0..2c9bfeb20541c 100644
--- a/libc/config/baremetal/config.json
+++ b/libc/config/baremetal/config.json
@@ -28,7 +28,10 @@
     "LIBC_CONF_PRINTF_DISABLE_STRERROR": {
       "value": true
     },
-    "LIBC_CONF_PRINTF_DISABLE_WIDE" : {
+    "LIBC_CONF_PRINTF_DISABLE_WIDE": {
+      "value": true
+    },
+    "LIBC_COPT_PRINTF_DISABLE_BITINT": {
       "value": true
     }
   },
diff --git a/libc/config/config.json b/libc/config/config.json
index b37154e294ec9..54d1282df6293 100644
--- a/libc/config/config.json
+++ b/libc/config/config.json
@@ -40,7 +40,6 @@
       "value": false,
       "doc": "Use an alternative printf float implementation based on 320-bit floats"
     },
-
     "LIBC_CONF_PRINTF_DISABLE_FIXED_POINT": {
       "value": false,
       "doc": "Disable printing fixed point values in printf and friends."
@@ -56,6 +55,10 @@
     "LIBC_CONF_PRINTF_DISABLE_WIDE": {
       "value": false,
       "doc": "Disable handling wide characters for printf and friends."
+    },
+    "LIBC_COPT_PRINTF_DISABLE_BITINT": {
+      "value": false,
+      "doc": "Disable bitint length modifiers to reduce code size. Specifically the wNUM and wfNUM modifiers."
     }
   },
   "scanf": {
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index 0813ab3554216..e6bf4b20ef59e 100644
--- a/libc/docs/configure.rst
+++ b/libc/docs/configure.rst
@@ -50,6 +50,7 @@ to learn about the defaults for your platform and target.
     - ``LIBC_CONF_PRINTF_FLOAT_TO_STR_USE_FLOAT320``: Use an alternative printf float implementation based on 320-bit floats
     - ``LIBC_CONF_PRINTF_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE``: Use large table for better printf long double performance.
     - ``LIBC_CONF_PRINTF_RUNTIME_DISPATCH``: Use dynamic dispatch for the output mechanism to reduce code size.
+    - ``LIBC_COPT_PRINTF_DISABLE_BITINT``: Disable bitint length modifiers to reduce code size. Specifically the wNUM and wfNUM modifiers.
 * **"pthread" options**
     - ``LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT``: Default number of spins before blocking if a mutex is in contention (default to 100).
     - ``LIBC_CONF_RWLOCK_DEFAULT_SPIN_COUNT``: Default number of spins before blocking if a rwlock is in contention (default to 100).
diff --git a/libc/docs/dev/printf_behavior.rst b/libc/docs/dev/printf_behavior.rst
index a825da55367bb..4b53e0b85f6d2 100644
--- a/libc/docs/dev/printf_behavior.rst
+++ b/libc/docs/dev/printf_behavior.rst
@@ -72,12 +72,18 @@ invalid. This reduces code size. This has no effect if the current compiler does
 not support fixed point numbers.
 
 LIBC_COPT_PRINTF_DISABLE_WIDE
---------------------------------
+-----------------------------
 When set, this flag disables support for wide characters (%lc and %ls). Any
 conversions will be ignored. This reduces code size. This will be set by default
 on windows platforms as current printf implementation does not support UTF-16 wide
 characters.
 
+LIBC_COPT_PRINTF_DISABLE_BITINT
+-------------------------------
+When set, this flag disables the bit int length modifiers wNUM and wfNUM. The
+length modifiers will be treated as if they don't exist, so conversions using
+them will be treated as invalid. This reduces code size.
+
 .. _printf_no_nullptr_checks:
 
 LIBC_COPT_PRINTF_NO_NULLPTR_CHECKS
diff --git a/libc/src/stdio/printf_core/converter_utils.h b/libc/src/stdio/printf_core/converter_utils.h
index 3f25ebfd40ed9..ed656ffb6e72f 100644
--- a/libc/src/stdio/printf_core/converter_utils.h
+++ b/libc/src/stdio/printf_core/converter_utils.h
@@ -43,6 +43,7 @@ LIBC_INLINE uintmax_t apply_length_modifier(uintmax_t num,
     return num & cpp::numeric_limits<uintptr_t>::max();
   case LengthModifier::j:
     return num; // j is intmax, so no mask is necessary.
+#ifndef LIBC_COPT_PRINTF_DISABLE_BITINT
   case LengthModifier::w:
   case LengthModifier::wf: {
     uintmax_t mask;
@@ -55,6 +56,7 @@ LIBC_INLINE uintmax_t apply_length_modifier(uintmax_t num,
     }
     return num & mask;
   }
+#endif // LIBC_COPT_PRINTF_DISABLE_BITINT
   }
   __builtin_unreachable();
 }
diff --git a/libc/src/stdio/printf_core/core_structs.h b/libc/src/stdio/printf_core/core_structs.h
index d93fa962db90e..705865745db47 100644
--- a/libc/src/stdio/printf_core/core_structs.h
+++ b/libc/src/stdio/printf_core/core_structs.h
@@ -24,7 +24,21 @@ namespace printf_core {
 
 // These length modifiers match the length modifiers in the format string, which
 // is why they are formatted differently from the rest of the file.
-enum class LengthModifier { hh, h, l, ll, j, z, t, L, w, wf, none };
+enum class LengthModifier {
+  hh,
+  h,
+  l,
+  ll,
+  j,
+  z,
+  t,
+  L,
+#ifndef LIBC_COPT_PRINTF_DISABLE_BITINT
+  w,
+  wf,
+#endif // LIBC_COPT_PRINTF_DISABLE_BITINT
+  none
+};
 
 struct LengthSpec {
   LengthModifier lm;
diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index a3b62991bcec9..d70a3aa91ce61 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -224,6 +224,7 @@ template <typename ArgProvider> class Parser {
           WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, ptrdiff_t, conv_index);
           break;
 
+#ifndef LIBC_COPT_PRINTF_DISABLE_BITINT
         case (LengthModifier::w):
         case (LengthModifier::wf):
           if (bw == 0) {
@@ -238,6 +239,7 @@ template <typename ArgProvider> class Parser {
             WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, intmax_t, conv_index);
           }
           break;
+#endif // LIBC_COPT_PRINTF_DISABLE_BITINT
         }
         break;
 #ifndef LIBC_COPT_PRINTF_DISABLE_FLOAT
@@ -360,6 +362,7 @@ template <typename ArgProvider> class Parser {
         ++*local_pos;
         return {LengthModifier::l, 0};
       }
+#ifndef LIBC_COPT_PRINTF_DISABLE_BITINT
     case ('w'): {
       LengthModifier lm;
       if (str[*local_pos + 1] == 'f') {
@@ -376,6 +379,7 @@ template <typename ArgProvider> class Parser {
       }
       return {lm, 0};
     }
+#endif // LIBC_COPT_PRINTF_DISABLE_BITINT
     case ('h'):
       if (str[*local_pos + 1] == 'h') {
         *local_pos += 2;
@@ -629,6 +633,7 @@ template <typename ArgProvider> class Parser {
           case (LengthModifier::t):
             conv_size = type_desc_from_type<ptrdiff_t>();
             break;
+#ifndef LIBC_COPT_PRINTF_DISABLE_BITINT
           case (LengthModifier::w):
           case (LengthModifier::wf):
             if (bw <= cpp::numeric_limits<unsigned int>::digits) {
@@ -641,6 +646,7 @@ template <typename ArgProvider> class Parser {
               conv_size = type_desc_from_type<intmax_t>();
             }
             break;
+#endif // LIBC_COPT_PRINTF_DISABLE_BITINT
           }
           break;
 #ifndef LIBC_COPT_PRINTF_DISABLE_FLOAT
diff --git a/libc/src/stdio/printf_core/write_int_converter.h b/libc/src/stdio/printf_core/write_int_converter.h
index 04b2bef05bc7b..0c7efedb5f3bf 100644
--- a/libc/src/stdio/printf_core/write_int_converter.h
+++ b/libc/src/stdio/printf_core/write_int_converter.h
@@ -57,8 +57,10 @@ LIBC_INLINE int convert_write_int(Writer<write_mode> *writer,
     *reinterpret_cast<ptrdiff_t *>(to_conv.conv_val_ptr) = written;
     break;
   case LengthModifier::j:
+#ifndef LIBC_COPT_PRINTF_DISABLE_BITINT
   case LengthModifier::w:
   case LengthModifier::wf:
+#endif // LIBC_COPT_PRINTF_DISABLE_BITINT
     *reinterpret_cast<uintmax_t *>(to_conv.conv_val_ptr) = written;
     break;
   }
diff --git a/libc/test/UnitTest/PrintfMatcher.cpp b/libc/test/UnitTest/PrintfMatcher.cpp
index 2ea1bbfcc6360..3a940aad8e435 100644
--- a/libc/test/UnitTest/PrintfMatcher.cpp
+++ b/libc/test/UnitTest/PrintfMatcher.cpp
@@ -71,8 +71,10 @@ static void display(FormatSection form) {
       CASE_LM(z);
       CASE_LM(t);
       CASE_LM(L);
+#ifndef LIBC_COPT_PRINTF_DISABLE_BITINT
       CASE_LM_BIT_WIDTH(w, form.bit_width);
       CASE_LM_BIT_WIDTH(wf, form.bit_width);
+#endif // LIBC_COPT_PRINTF_DISABLE_BITINT
     }
     tlog << "\n";
     tlog << "\tconversion name: " << form.conv_name << "\n";
diff --git a/libc/test/src/stdio/printf_core/parser_test.cpp b/libc/test/src/stdio/printf_core/parser_test.cpp
index 9d192828860f7..4e1b796ec9b65 100644
--- a/libc/test/src/stdio/printf_core/parser_test.cpp
+++ b/libc/test/src/stdio/printf_core/parser_test.cpp
@@ -230,6 +230,8 @@ TEST(LlvmLibcPrintfParserTest, EvalOneArgWithLongLengthModifier) {
   ASSERT_PFORMAT_EQ(expected, format_arr[0]);
 }
 
+
+#ifndef LIBC_COPT_PRINTF_DISABLE_BITINT
 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithBitWidthLengthModifier) {
   LIBC_NAMESPACE::printf_core::FormatSection format_arr[10];
   const char *str = "%w32d";
@@ -267,6 +269,7 @@ TEST(LlvmLibcPrintfParserTest, EvalOneArgWithFastBitWidthLengthModifier) {
 
   ASSERT_PFORMAT_EQ(expected, format_arr[0]);
 }
+#endif // LIBC_COPT_PRINTF_DISABLE_BITINT
 
 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithAllOptions) {
   LIBC_NAMESPACE::printf_core::FormatSection format_arr[10];
diff --git a/libc/test/src/stdio/sprintf_test.cpp b/libc/test/src/stdio/sprintf_test.cpp
index 78186abb9966e..01d9c1056356a 100644
--- a/libc/test/src/stdio/sprintf_test.cpp
+++ b/libc/test/src/stdio/sprintf_test.cpp
@@ -151,6 +151,8 @@ TEST(LlvmLibcSPrintfTest, IntConv) {
   written = LIBC_NAMESPACE::sprintf(buff, "%lld", -9223372036854775807ll - 1ll);
   ASSERT_STREQ_LEN(written, buff, "-9223372036854775808"); // ll min
 
+#ifndef LIBC_COPT_PRINTF_DISABLE_BITINT
+  // Bit int width tests
   written = LIBC_NAMESPACE::sprintf(buff, "%w3d", 5807);
   ASSERT_STREQ_LEN(written, buff, "7");
 
@@ -218,6 +220,7 @@ TEST(LlvmLibcSPrintfTest, IntConv) {
 
   written = LIBC_NAMESPACE::sprintf(buff, "%wf999d", 9223372036854775807ll);
   ASSERT_STREQ_LEN(written, buff, "9223372036854775807");
+#endif // LIBC_COPT_PRINTF_DISABLE_BITINT
 
   // Min Width Tests.
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/180832


More information about the libc-commits mailing list