[libc-commits] [libc] [libc][printf] Break out floating point support behind weak symbols (PR #120612)

Daniel Thornburgh via libc-commits libc-commits at lists.llvm.org
Thu Dec 19 11:15:54 PST 2024


https://github.com/mysterymath updated https://github.com/llvm/llvm-project/pull/120612

>From ccbb6faee338e7cd9c93615cfaf666e61ce685e8 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Mon, 16 Dec 2024 16:42:58 -0800
Subject: [PATCH 01/13] Break float out of printf (with no way to bring it back
 in)

---
 .../stdio/printf_core/float_dec_converter.cpp |  2 ++
 .../stdio/printf_core/float_dec_converter.h   | 21 +++++++++++++------
 libc/src/stdio/printf_core/printf_config.h    | 10 +++++++++
 3 files changed, 27 insertions(+), 6 deletions(-)
 create mode 100644 libc/src/stdio/printf_core/float_dec_converter.cpp

diff --git a/libc/src/stdio/printf_core/float_dec_converter.cpp b/libc/src/stdio/printf_core/float_dec_converter.cpp
new file mode 100644
index 00000000000000..0b4b74c0ce8bd1
--- /dev/null
+++ b/libc/src/stdio/printf_core/float_dec_converter.cpp
@@ -0,0 +1,2 @@
+#define LIBC_PRINTF_DEFINE_SPLIT
+#include "src/stdio/printf_core/float_dec_converter_impl.h"
diff --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h
index d93457fcafd7f9..e30a2fec834f5f 100644
--- a/libc/src/stdio/printf_core/float_dec_converter.h
+++ b/libc/src/stdio/printf_core/float_dec_converter.h
@@ -1106,9 +1106,10 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer *writer,
   }
 }
 
+#ifdef LIBC_PRINTF_DEFINE_SPLIT
 // TODO: unify the float converters to remove the duplicated checks for inf/nan.
-LIBC_INLINE int convert_float_decimal(Writer *writer,
-                                      const FormatSection &to_conv) {
+LIBC_PRINTF_SPLIT_FUNCTION int
+convert_float_decimal(Writer *writer, const FormatSection &to_conv) {
   if (to_conv.length_modifier == LengthModifier::L) {
     fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
     fputil::FPBits<long double> float_bits(float_raw);
@@ -1128,8 +1129,8 @@ LIBC_INLINE int convert_float_decimal(Writer *writer,
   return convert_inf_nan(writer, to_conv);
 }
 
-LIBC_INLINE int convert_float_dec_exp(Writer *writer,
-                                      const FormatSection &to_conv) {
+LIBC_PRINTF_SPLIT_FUNCTION int
+convert_float_dec_exp(Writer *writer, const FormatSection &to_conv) {
   if (to_conv.length_modifier == LengthModifier::L) {
     fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
     fputil::FPBits<long double> float_bits(float_raw);
@@ -1149,8 +1150,8 @@ LIBC_INLINE int convert_float_dec_exp(Writer *writer,
   return convert_inf_nan(writer, to_conv);
 }
 
-LIBC_INLINE int convert_float_dec_auto(Writer *writer,
-                                       const FormatSection &to_conv) {
+LIBC_PRINTF_SPLIT_FUNCTION int
+convert_float_dec_auto(Writer *writer, const FormatSection &to_conv) {
   if (to_conv.length_modifier == LengthModifier::L) {
     fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
     fputil::FPBits<long double> float_bits(float_raw);
@@ -1169,6 +1170,14 @@ LIBC_INLINE int convert_float_dec_auto(Writer *writer,
 
   return convert_inf_nan(writer, to_conv);
 }
+#else
+[[gnu::weak]] int convert_float_decimal(Writer *writer,
+                                        const FormatSection &to_conv);
+[[gnu::weak]] int convert_float_dec_exp(Writer *writer,
+                                        const FormatSection &to_conv);
+[[gnu::weak]] int convert_float_dec_auto(Writer *writer,
+                                         const FormatSection &to_conv);
+#endif
 
 } // namespace printf_core
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/printf_core/printf_config.h b/libc/src/stdio/printf_core/printf_config.h
index 8a48abdd170eca..c37e0bb767803b 100644
--- a/libc/src/stdio/printf_core/printf_config.h
+++ b/libc/src/stdio/printf_core/printf_config.h
@@ -48,4 +48,14 @@
 
 // LIBC_COPT_PRINTF_NO_NULLPTR_CHECKS
 
+#ifdef LIBC_COPT_PRINTF_SPLIT
+// Split printf function definitions must be strong and non-inline.
+#define LIBC_PRINTF_SPLIT_FUNCTION
+#else
+// Function definitions that could be split but are not must be inline in
+// headers.
+#define LIBC_PRINTF_SPLIT_FUNCTION LIBC_INLINE
+#define LIBC_PRINTF_DEFINE_SPLIT
+#endif
+
 #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_PRINTF_CONFIG_H

>From f20628e656cd53c5b83e4fa451763965ac9b644f Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 17 Dec 2024 11:15:30 -0800
Subject: [PATCH 02/13] Add CMake forwarding (not hooked upt to config

---
 libc/src/stdio/printf_core/CMakeLists.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index 9eaffe2f7ed621..8c6064cd1544b0 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -22,6 +22,9 @@ endif()
 if(LIBC_CONF_PRINTF_DISABLE_STRERROR)
   list(APPEND printf_config_copts "-DLIBC_COPT_PRINTF_DISABLE_STRERROR")
 endif()
+if(LIBC_CONF_PRINTF_SPLIT)
+  list(APPEND printf_config_copts "-DLIBC_COPT_PRINTF_SPLIT")
+endif()
 if(printf_config_copts)
   list(PREPEND printf_config_copts "COMPILE_OPTIONS")
 endif()

>From f0e99b1426360502696ab0e1bb62b6d105ed5105 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 17 Dec 2024 11:18:41 -0800
Subject: [PATCH 03/13] Add object library for float_dec_converter

---
 libc/src/stdio/printf_core/CMakeLists.txt | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index 8c6064cd1544b0..140878ba0350d8 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -113,6 +113,27 @@ add_object_library(
     libc.src.__support.StringUtil.error_to_string
 )
 
+if(LIBC_CONF_PRINTF_SPLIT)
+add_object_library(
+  float_dec_converter
+  SRCS
+    float_dec_converter.cpp
+  HDRS
+    float_dec_converter.h
+  DEPENDS
+    .core_structs
+    .printf_config
+    .writer
+    libc.src.__support.big_int
+    libc.src.__support.CPP.string_view
+    libc.src.__support.float_to_string
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.rounding_mode
+    libc.src.__support.integer_to_string
+    libc.src.__support.libc_assert
+)
+endif()
+
 add_object_library(
   printf_main
   SRCS

>From 7bf95ace9f0b90a9916b9a3863d35b3199924c45 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 17 Dec 2024 11:21:03 -0800
Subject: [PATCH 04/13] Let's just use a list instead

---
 libc/src/stdio/printf_core/CMakeLists.txt | 28 +++++------------------
 1 file changed, 6 insertions(+), 22 deletions(-)

diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index 140878ba0350d8..bf26717dab552d 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -76,10 +76,15 @@ add_object_library(
     libc.src.string.memory_utils.inline_memset
 )
 
+set(printf_converter_srcs converter.cpp)
+if(LIBC_CONF_PRINTF_SPLIT)
+  list(APPEND printf_converter_srcs float_dec_converter.cpp)
+endif()
+
 add_object_library(
   converter
   SRCS
-    converter.cpp
+  ${printf_converter_srcs}
   HDRS
     converter.h
     converter_atlas.h
@@ -113,27 +118,6 @@ add_object_library(
     libc.src.__support.StringUtil.error_to_string
 )
 
-if(LIBC_CONF_PRINTF_SPLIT)
-add_object_library(
-  float_dec_converter
-  SRCS
-    float_dec_converter.cpp
-  HDRS
-    float_dec_converter.h
-  DEPENDS
-    .core_structs
-    .printf_config
-    .writer
-    libc.src.__support.big_int
-    libc.src.__support.CPP.string_view
-    libc.src.__support.float_to_string
-    libc.src.__support.FPUtil.fp_bits
-    libc.src.__support.FPUtil.rounding_mode
-    libc.src.__support.integer_to_string
-    libc.src.__support.libc_assert
-)
-endif()
-
 add_object_library(
   printf_main
   SRCS

>From 8020767e24dd39f60d06f2d2763774bfa2b9ff28 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 17 Dec 2024 13:10:06 -0800
Subject: [PATCH 05/13] Add dummy functions to bring things in

---
 libc/src/stdio/printf_core/CMakeLists.txt          | 4 +++-
 libc/src/stdio/printf_core/float_dec_converter.cpp | 5 ++++-
 libc/src/stdio/printf_core/float_dec_converter.h   | 3 +++
 libc/src/stdio/printf_core/split_float.cpp         | 7 +++++++
 4 files changed, 17 insertions(+), 2 deletions(-)
 create mode 100644 libc/src/stdio/printf_core/split_float.cpp

diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index bf26717dab552d..2b8cb49fedb521 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -78,7 +78,9 @@ add_object_library(
 
 set(printf_converter_srcs converter.cpp)
 if(LIBC_CONF_PRINTF_SPLIT)
-  list(APPEND printf_converter_srcs float_dec_converter.cpp)
+  list(APPEND printf_converter_srcs
+    float_dec_converter.cpp
+    split_float.cpp)
 endif()
 
 add_object_library(
diff --git a/libc/src/stdio/printf_core/float_dec_converter.cpp b/libc/src/stdio/printf_core/float_dec_converter.cpp
index 0b4b74c0ce8bd1..21726da5c14e7d 100644
--- a/libc/src/stdio/printf_core/float_dec_converter.cpp
+++ b/libc/src/stdio/printf_core/float_dec_converter.cpp
@@ -1,2 +1,5 @@
 #define LIBC_PRINTF_DEFINE_SPLIT
-#include "src/stdio/printf_core/float_dec_converter_impl.h"
+#include "src/stdio/printf_core/float_dec_converter.h"
+
+// Define trivial function that can be used to bring this file into the link.
+void __libc_printf_float_dec_converter() {}
diff --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h
index e30a2fec834f5f..a5e4574c879957 100644
--- a/libc/src/stdio/printf_core/float_dec_converter.h
+++ b/libc/src/stdio/printf_core/float_dec_converter.h
@@ -1182,4 +1182,7 @@ convert_float_dec_auto(Writer *writer, const FormatSection &to_conv) {
 } // namespace printf_core
 } // namespace LIBC_NAMESPACE_DECL
 
+// Call this function to bring a split implementation into the link.
+extern "C" void __libc_printf_float_dec_converter();
+
 #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_DEC_CONVERTER_H
diff --git a/libc/src/stdio/printf_core/split_float.cpp b/libc/src/stdio/printf_core/split_float.cpp
new file mode 100644
index 00000000000000..a265983cb9d14a
--- /dev/null
+++ b/libc/src/stdio/printf_core/split_float.cpp
@@ -0,0 +1,7 @@
+#include "src/stdio/printf_core/float_dec_converter.h"
+
+// Bring this file into the link if __printf_float is referenced.
+void __printf_float() {
+  // Bring the printf floating point implementation into the link.
+  __libc_printf_float_dec_converter();
+}

>From 4d54f34a1a591bf6e18499e052295afcdccb4956 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Wed, 18 Dec 2024 13:41:37 -0800
Subject: [PATCH 06/13] Break out hex float too; finishes converter fns

---
 libc/src/stdio/printf_core/CMakeLists.txt          |  1 +
 libc/src/stdio/printf_core/float_hex_converter.cpp |  5 +++++
 libc/src/stdio/printf_core/float_hex_converter.h   | 12 ++++++++++--
 libc/src/stdio/printf_core/split_float.cpp         |  2 ++
 4 files changed, 18 insertions(+), 2 deletions(-)
 create mode 100644 libc/src/stdio/printf_core/float_hex_converter.cpp

diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index 2b8cb49fedb521..ad69ad047e0ed9 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -80,6 +80,7 @@ set(printf_converter_srcs converter.cpp)
 if(LIBC_CONF_PRINTF_SPLIT)
   list(APPEND printf_converter_srcs
     float_dec_converter.cpp
+    float_hex_converter.cpp
     split_float.cpp)
 endif()
 
diff --git a/libc/src/stdio/printf_core/float_hex_converter.cpp b/libc/src/stdio/printf_core/float_hex_converter.cpp
new file mode 100644
index 00000000000000..cdb28356fe48c1
--- /dev/null
+++ b/libc/src/stdio/printf_core/float_hex_converter.cpp
@@ -0,0 +1,5 @@
+#define LIBC_PRINTF_DEFINE_SPLIT
+#include "src/stdio/printf_core/float_hex_converter.h"
+
+// Define trivial function that can be used to bring this file into the link.
+void __libc_printf_float_hex_converter() {}
diff --git a/libc/src/stdio/printf_core/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h
index b264b5cf207283..3fe550252a4541 100644
--- a/libc/src/stdio/printf_core/float_hex_converter.h
+++ b/libc/src/stdio/printf_core/float_hex_converter.h
@@ -25,8 +25,9 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace printf_core {
 
-LIBC_INLINE int convert_float_hex_exp(Writer *writer,
-                                      const FormatSection &to_conv) {
+#ifdef LIBC_PRINTF_DEFINE_SPLIT
+LIBC_PRINTF_SPLIT_FUNCTION int
+convert_float_hex_exp(Writer *writer, const FormatSection &to_conv) {
   using LDBits = fputil::FPBits<long double>;
   using StorageType = LDBits::StorageType;
 
@@ -253,8 +254,15 @@ LIBC_INLINE int convert_float_hex_exp(Writer *writer,
   }
   return WRITE_OK;
 }
+#else
+[[gnu::weak]] int convert_float_hex_exp(Writer *writer,
+                                        const FormatSection &to_conv);
+#endif
 
 } // namespace printf_core
 } // namespace LIBC_NAMESPACE_DECL
 
+// Call this function to bring a split implementation into the link.
+extern "C" void __libc_printf_float_hex_converter();
+
 #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_HEX_CONVERTER_H
diff --git a/libc/src/stdio/printf_core/split_float.cpp b/libc/src/stdio/printf_core/split_float.cpp
index a265983cb9d14a..3dc5d7aa03c27a 100644
--- a/libc/src/stdio/printf_core/split_float.cpp
+++ b/libc/src/stdio/printf_core/split_float.cpp
@@ -1,7 +1,9 @@
 #include "src/stdio/printf_core/float_dec_converter.h"
+#include "src/stdio/printf_core/float_hex_converter.h"
 
 // Bring this file into the link if __printf_float is referenced.
 void __printf_float() {
   // Bring the printf floating point implementation into the link.
   __libc_printf_float_dec_converter();
+  __libc_printf_float_hex_converter();
 }

>From 5b4f2a5e304c0c9fb0fe160bd39b1debbdffb03a Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Wed, 18 Dec 2024 15:25:48 -0800
Subject: [PATCH 07/13] Break out arg val writing

---
 libc/src/stdio/printf_core/parser.h | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index acbbaa25b1c9da..0030fdfcc98a23 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -235,11 +235,7 @@ template <typename ArgProvider> class Parser {
       case ('A'):
       case ('g'):
       case ('G'):
-        if (lm != LengthModifier::L) {
-          WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, double, conv_index);
-        } else {
-          WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, long double, conv_index);
-        }
+        write_float_arg_val(section, lm, conv_index);
         break;
 #endif // LIBC_COPT_PRINTF_DISABLE_FLOAT
 #ifdef LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT
@@ -297,6 +293,14 @@ template <typename ArgProvider> class Parser {
     return section;
   }
 
+#ifdef LIBC_PRINTF_DEFINE_SPLIT
+  void write_float_arg_val(FormatSection &section, LengthModifier lm,
+                           size_t conv_index);
+#else
+  [[gnu::weak]] void write_float_arg_val(FormatSection &section, LengthModifier lm,
+                           size_t conv_index);
+#endif
+
 private:
   // parse_flags parses the flags inside a format string. It assumes that
   // str[*local_pos] is inside a format specifier, and parses any flags it
@@ -680,6 +684,19 @@ template <typename ArgProvider> class Parser {
 #endif // LIBC_COPT_PRINTF_DISABLE_INDEX_MODE
 };
 
+#ifdef LIBC_PRINTF_DEFINE_SPLIT
+template <typename ArgParser>
+LIBC_PRINTF_SPLIT_FUNCTION void Parser<ArgParser>::write_float_arg_val(FormatSection &section,
+                                                        LengthModifier lm,
+                                                        size_t conv_index) {
+  if (lm != LengthModifier::L) {
+    WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, double, conv_index);
+  } else {
+    WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, long double, conv_index);
+  }
+}
+#endif
+
 } // namespace printf_core
 } // namespace LIBC_NAMESPACE_DECL
 

>From 577b204a7684b2fd358798737268b5b6caf64a88 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Wed, 18 Dec 2024 15:47:50 -0800
Subject: [PATCH 08/13] Refactor split attributes

---
 .../stdio/printf_core/float_dec_converter.h   | 20 +++++++++----------
 .../stdio/printf_core/float_hex_converter.h   | 10 +++++-----
 libc/src/stdio/printf_core/parser.h           | 10 ++--------
 libc/src/stdio/printf_core/printf_config.h    |  9 ++++-----
 4 files changed, 21 insertions(+), 28 deletions(-)

diff --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h
index a5e4574c879957..0e5cdb6904f953 100644
--- a/libc/src/stdio/printf_core/float_dec_converter.h
+++ b/libc/src/stdio/printf_core/float_dec_converter.h
@@ -1106,9 +1106,16 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer *writer,
   }
 }
 
+LIBC_PRINTF_SPLIT_DECL int convert_float_decimal(Writer *writer,
+                                                 const FormatSection &to_conv);
+LIBC_PRINTF_SPLIT_DECL int convert_float_dec_exp(Writer *writer,
+                                                 const FormatSection &to_conv);
+LIBC_PRINTF_SPLIT_DECL int convert_float_dec_auto(Writer *writer,
+                                                  const FormatSection &to_conv);
+
 #ifdef LIBC_PRINTF_DEFINE_SPLIT
 // TODO: unify the float converters to remove the duplicated checks for inf/nan.
-LIBC_PRINTF_SPLIT_FUNCTION int
+LIBC_PRINTF_SPLIT_DEFN int
 convert_float_decimal(Writer *writer, const FormatSection &to_conv) {
   if (to_conv.length_modifier == LengthModifier::L) {
     fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
@@ -1129,7 +1136,7 @@ convert_float_decimal(Writer *writer, const FormatSection &to_conv) {
   return convert_inf_nan(writer, to_conv);
 }
 
-LIBC_PRINTF_SPLIT_FUNCTION int
+LIBC_PRINTF_SPLIT_DEFN int
 convert_float_dec_exp(Writer *writer, const FormatSection &to_conv) {
   if (to_conv.length_modifier == LengthModifier::L) {
     fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
@@ -1150,7 +1157,7 @@ convert_float_dec_exp(Writer *writer, const FormatSection &to_conv) {
   return convert_inf_nan(writer, to_conv);
 }
 
-LIBC_PRINTF_SPLIT_FUNCTION int
+LIBC_PRINTF_SPLIT_DEFN int
 convert_float_dec_auto(Writer *writer, const FormatSection &to_conv) {
   if (to_conv.length_modifier == LengthModifier::L) {
     fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
@@ -1170,13 +1177,6 @@ convert_float_dec_auto(Writer *writer, const FormatSection &to_conv) {
 
   return convert_inf_nan(writer, to_conv);
 }
-#else
-[[gnu::weak]] int convert_float_decimal(Writer *writer,
-                                        const FormatSection &to_conv);
-[[gnu::weak]] int convert_float_dec_exp(Writer *writer,
-                                        const FormatSection &to_conv);
-[[gnu::weak]] int convert_float_dec_auto(Writer *writer,
-                                         const FormatSection &to_conv);
 #endif
 
 } // namespace printf_core
diff --git a/libc/src/stdio/printf_core/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h
index 3fe550252a4541..6d018aa0ecaaed 100644
--- a/libc/src/stdio/printf_core/float_hex_converter.h
+++ b/libc/src/stdio/printf_core/float_hex_converter.h
@@ -25,9 +25,12 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace printf_core {
 
+LIBC_PRINTF_SPLIT_DECL int convert_float_hex_exp(Writer *writer,
+                                                 const FormatSection &to_conv);
+
 #ifdef LIBC_PRINTF_DEFINE_SPLIT
-LIBC_PRINTF_SPLIT_FUNCTION int
-convert_float_hex_exp(Writer *writer, const FormatSection &to_conv) {
+LIBC_PRINTF_SPLIT_DEFN int convert_float_hex_exp(Writer *writer,
+                                                 const FormatSection &to_conv) {
   using LDBits = fputil::FPBits<long double>;
   using StorageType = LDBits::StorageType;
 
@@ -254,9 +257,6 @@ convert_float_hex_exp(Writer *writer, const FormatSection &to_conv) {
   }
   return WRITE_OK;
 }
-#else
-[[gnu::weak]] int convert_float_hex_exp(Writer *writer,
-                                        const FormatSection &to_conv);
 #endif
 
 } // namespace printf_core
diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index 0030fdfcc98a23..89b8d65e8d988c 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -293,13 +293,7 @@ template <typename ArgProvider> class Parser {
     return section;
   }
 
-#ifdef LIBC_PRINTF_DEFINE_SPLIT
-  void write_float_arg_val(FormatSection &section, LengthModifier lm,
-                           size_t conv_index);
-#else
-  [[gnu::weak]] void write_float_arg_val(FormatSection &section, LengthModifier lm,
-                           size_t conv_index);
-#endif
+  LIBC_PRINTF_SPLIT_DECL void write_float_arg_val(FormatSection &section, LengthModifier lm, size_t conv_index);
 
 private:
   // parse_flags parses the flags inside a format string. It assumes that
@@ -686,7 +680,7 @@ template <typename ArgProvider> class Parser {
 
 #ifdef LIBC_PRINTF_DEFINE_SPLIT
 template <typename ArgParser>
-LIBC_PRINTF_SPLIT_FUNCTION void Parser<ArgParser>::write_float_arg_val(FormatSection &section,
+LIBC_PRINTF_SPLIT_DEFN void Parser<ArgParser>::write_float_arg_val(FormatSection &section,
                                                         LengthModifier lm,
                                                         size_t conv_index) {
   if (lm != LengthModifier::L) {
diff --git a/libc/src/stdio/printf_core/printf_config.h b/libc/src/stdio/printf_core/printf_config.h
index c37e0bb767803b..4cfca8de919d5c 100644
--- a/libc/src/stdio/printf_core/printf_config.h
+++ b/libc/src/stdio/printf_core/printf_config.h
@@ -49,12 +49,11 @@
 // LIBC_COPT_PRINTF_NO_NULLPTR_CHECKS
 
 #ifdef LIBC_COPT_PRINTF_SPLIT
-// Split printf function definitions must be strong and non-inline.
-#define LIBC_PRINTF_SPLIT_FUNCTION
+#define LIBC_PRINTF_SPLIT_DECL [[gnu::weak]]
+#define LIBC_PRINTF_SPLIT_DEFN
 #else
-// Function definitions that could be split but are not must be inline in
-// headers.
-#define LIBC_PRINTF_SPLIT_FUNCTION LIBC_INLINE
+#define LIBC_PRINTF_SPLIT_DECL
+#define LIBC_PRINTF_SPLIT_DEFN LIBC_INLINE
 #define LIBC_PRINTF_DEFINE_SPLIT
 #endif
 

>From 1d7eb904cbd1faff2c6ea896c7d0e6a7447399aa Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Wed, 18 Dec 2024 15:50:35 -0800
Subject: [PATCH 09/13] Refactor float splitting

---
 libc/src/stdio/printf_core/CMakeLists.txt          | 5 +----
 libc/src/stdio/printf_core/float_dec_converter.cpp | 5 -----
 libc/src/stdio/printf_core/float_dec_converter.h   | 3 ---
 libc/src/stdio/printf_core/float_hex_converter.cpp | 5 -----
 libc/src/stdio/printf_core/float_hex_converter.h   | 3 ---
 libc/src/stdio/printf_core/split_float.cpp         | 8 +++-----
 6 files changed, 4 insertions(+), 25 deletions(-)
 delete mode 100644 libc/src/stdio/printf_core/float_dec_converter.cpp
 delete mode 100644 libc/src/stdio/printf_core/float_hex_converter.cpp

diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index ad69ad047e0ed9..7866c004246fc3 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -78,10 +78,7 @@ add_object_library(
 
 set(printf_converter_srcs converter.cpp)
 if(LIBC_CONF_PRINTF_SPLIT)
-  list(APPEND printf_converter_srcs
-    float_dec_converter.cpp
-    float_hex_converter.cpp
-    split_float.cpp)
+  list(APPEND printf_converter_srcs split_float.cpp)
 endif()
 
 add_object_library(
diff --git a/libc/src/stdio/printf_core/float_dec_converter.cpp b/libc/src/stdio/printf_core/float_dec_converter.cpp
deleted file mode 100644
index 21726da5c14e7d..00000000000000
--- a/libc/src/stdio/printf_core/float_dec_converter.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#define LIBC_PRINTF_DEFINE_SPLIT
-#include "src/stdio/printf_core/float_dec_converter.h"
-
-// Define trivial function that can be used to bring this file into the link.
-void __libc_printf_float_dec_converter() {}
diff --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h
index 0e5cdb6904f953..5265f71499a42e 100644
--- a/libc/src/stdio/printf_core/float_dec_converter.h
+++ b/libc/src/stdio/printf_core/float_dec_converter.h
@@ -1182,7 +1182,4 @@ convert_float_dec_auto(Writer *writer, const FormatSection &to_conv) {
 } // namespace printf_core
 } // namespace LIBC_NAMESPACE_DECL
 
-// Call this function to bring a split implementation into the link.
-extern "C" void __libc_printf_float_dec_converter();
-
 #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_DEC_CONVERTER_H
diff --git a/libc/src/stdio/printf_core/float_hex_converter.cpp b/libc/src/stdio/printf_core/float_hex_converter.cpp
deleted file mode 100644
index cdb28356fe48c1..00000000000000
--- a/libc/src/stdio/printf_core/float_hex_converter.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#define LIBC_PRINTF_DEFINE_SPLIT
-#include "src/stdio/printf_core/float_hex_converter.h"
-
-// Define trivial function that can be used to bring this file into the link.
-void __libc_printf_float_hex_converter() {}
diff --git a/libc/src/stdio/printf_core/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h
index 6d018aa0ecaaed..b017888021e04b 100644
--- a/libc/src/stdio/printf_core/float_hex_converter.h
+++ b/libc/src/stdio/printf_core/float_hex_converter.h
@@ -262,7 +262,4 @@ LIBC_PRINTF_SPLIT_DEFN int convert_float_hex_exp(Writer *writer,
 } // namespace printf_core
 } // namespace LIBC_NAMESPACE_DECL
 
-// Call this function to bring a split implementation into the link.
-extern "C" void __libc_printf_float_hex_converter();
-
 #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_HEX_CONVERTER_H
diff --git a/libc/src/stdio/printf_core/split_float.cpp b/libc/src/stdio/printf_core/split_float.cpp
index 3dc5d7aa03c27a..3bf4af80d95af0 100644
--- a/libc/src/stdio/printf_core/split_float.cpp
+++ b/libc/src/stdio/printf_core/split_float.cpp
@@ -1,9 +1,7 @@
+#define LIBC_PRINTF_DEFINE_SPLIT
 #include "src/stdio/printf_core/float_dec_converter.h"
 #include "src/stdio/printf_core/float_hex_converter.h"
+#include "src/stdio/printf_core/parser.h"
 
 // Bring this file into the link if __printf_float is referenced.
-void __printf_float() {
-  // Bring the printf floating point implementation into the link.
-  __libc_printf_float_dec_converter();
-  __libc_printf_float_hex_converter();
-}
+void __printf_float() {}

>From 6c9d596fc987161580ce8abbdb5613509012058f Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Wed, 18 Dec 2024 16:03:56 -0800
Subject: [PATCH 10/13] Break out float_type_desc

---
 libc/src/stdio/printf_core/parser.h | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index 89b8d65e8d988c..d2cd60e8480bef 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -294,6 +294,7 @@ template <typename ArgProvider> class Parser {
   }
 
   LIBC_PRINTF_SPLIT_DECL void write_float_arg_val(FormatSection &section, LengthModifier lm, size_t conv_index);
+  LIBC_PRINTF_SPLIT_DECL TypeDesc float_type_desc(LengthModifier lm);
 
 private:
   // parse_flags parses the flags inside a format string. It assumes that
@@ -626,10 +627,7 @@ template <typename ArgProvider> class Parser {
         case ('A'):
         case ('g'):
         case ('G'):
-          if (lm != LengthModifier::L)
-            conv_size = type_desc_from_type<double>();
-          else
-            conv_size = type_desc_from_type<long double>();
+          return float_type_desc(lm);
           break;
 #endif // LIBC_COPT_PRINTF_DISABLE_FLOAT
 #ifdef LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT
@@ -680,15 +678,24 @@ template <typename ArgProvider> class Parser {
 
 #ifdef LIBC_PRINTF_DEFINE_SPLIT
 template <typename ArgParser>
-LIBC_PRINTF_SPLIT_DEFN void Parser<ArgParser>::write_float_arg_val(FormatSection &section,
-                                                        LengthModifier lm,
-                                                        size_t conv_index) {
+LIBC_PRINTF_SPLIT_DEFN void
+Parser<ArgParser>::write_float_arg_val(FormatSection &section,
+                                       LengthModifier lm, size_t conv_index) {
   if (lm != LengthModifier::L) {
     WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, double, conv_index);
   } else {
     WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, long double, conv_index);
   }
 }
+
+template <typename ArgParser>
+LIBC_PRINTF_SPLIT_DEFN TypeDesc
+Parser<ArgParser>::float_type_desc(LengthModifier lm) {
+  if (lm != LengthModifier::L)
+    return type_desc_from_type<double>();
+  else
+    return type_desc_from_type<long double>();
+}
 #endif
 
 } // namespace printf_core

>From add704ac282b5b3e5fd1455d3f914e8491accb17 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Thu, 19 Dec 2024 09:03:36 -0800
Subject: [PATCH 11/13] Break out remaining type desc stuffs

---
 libc/src/stdio/printf_core/parser.h | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index d2cd60e8480bef..3ac677e5d05575 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -295,6 +295,7 @@ template <typename ArgProvider> class Parser {
 
   LIBC_PRINTF_SPLIT_DECL void write_float_arg_val(FormatSection &section, LengthModifier lm, size_t conv_index);
   LIBC_PRINTF_SPLIT_DECL TypeDesc float_type_desc(LengthModifier lm);
+  LIBC_PRINTF_SPLIT_DECL bool advance_arg_if_float(TypeDesc cur_type_desc);
 
 private:
   // parse_flags parses the flags inside a format string. It assumes that
@@ -471,10 +472,8 @@ template <typename ArgProvider> class Parser {
         args_cur.template next_var<uint64_t>();
 #ifndef LIBC_COPT_PRINTF_DISABLE_FLOAT
       // Floating point numbers are stored separately from the other arguments.
-      else if (cur_type_desc == type_desc_from_type<double>())
-        args_cur.template next_var<double>();
-      else if (cur_type_desc == type_desc_from_type<long double>())
-        args_cur.template next_var<long double>();
+      else if (advance_arg_if_float(cur_type_desc))
+        ;
 #endif // LIBC_COPT_PRINTF_DISABLE_FLOAT
 #ifdef LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT
       // Floating point numbers may be stored separately from the other
@@ -696,6 +695,18 @@ Parser<ArgParser>::float_type_desc(LengthModifier lm) {
   else
     return type_desc_from_type<long double>();
 }
+
+template <typename ArgParser>
+LIBC_PRINTF_SPLIT_DEFN bool
+Parser<ArgParser>::advance_arg_if_float(TypeDesc cur_type_desc) {
+  if (cur_type_desc == type_desc_from_type<double>())
+      args_cur.template next_var<double>();
+  else if (cur_type_desc == type_desc_from_type<long double>())
+      args_cur.template next_var<long double>();
+  else
+    return false;
+  return true;
+}
 #endif
 
 } // namespace printf_core

>From d4d7183b8260f61fe51dc0ac6da3ef68c7bb8294 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Thu, 19 Dec 2024 11:03:50 -0800
Subject: [PATCH 12/13] Guard call to advance_arg_if_float

---
 libc/src/stdio/printf_core/parser.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index 3ac677e5d05575..eb94f7541823ca 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -472,7 +472,8 @@ template <typename ArgProvider> class Parser {
         args_cur.template next_var<uint64_t>();
 #ifndef LIBC_COPT_PRINTF_DISABLE_FLOAT
       // Floating point numbers are stored separately from the other arguments.
-      else if (advance_arg_if_float(cur_type_desc))
+      else if (&Parser::advance_arg_if_float &&
+               advance_arg_if_float(cur_type_desc))
         ;
 #endif // LIBC_COPT_PRINTF_DISABLE_FLOAT
 #ifdef LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT

>From 3b26e17d9ca074d23887f8cfa29781888d91b62a Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Thu, 19 Dec 2024 11:04:03 -0800
Subject: [PATCH 13/13] clang-format

---
 libc/src/stdio/printf_core/float_dec_converter.h | 8 ++++----
 libc/src/stdio/printf_core/parser.h              | 8 +++++---
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h
index 5265f71499a42e..968a900ff2f19b 100644
--- a/libc/src/stdio/printf_core/float_dec_converter.h
+++ b/libc/src/stdio/printf_core/float_dec_converter.h
@@ -1115,8 +1115,8 @@ LIBC_PRINTF_SPLIT_DECL int convert_float_dec_auto(Writer *writer,
 
 #ifdef LIBC_PRINTF_DEFINE_SPLIT
 // TODO: unify the float converters to remove the duplicated checks for inf/nan.
-LIBC_PRINTF_SPLIT_DEFN int
-convert_float_decimal(Writer *writer, const FormatSection &to_conv) {
+LIBC_PRINTF_SPLIT_DEFN int convert_float_decimal(Writer *writer,
+                                                 const FormatSection &to_conv) {
   if (to_conv.length_modifier == LengthModifier::L) {
     fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
     fputil::FPBits<long double> float_bits(float_raw);
@@ -1136,8 +1136,8 @@ convert_float_decimal(Writer *writer, const FormatSection &to_conv) {
   return convert_inf_nan(writer, to_conv);
 }
 
-LIBC_PRINTF_SPLIT_DEFN int
-convert_float_dec_exp(Writer *writer, const FormatSection &to_conv) {
+LIBC_PRINTF_SPLIT_DEFN int convert_float_dec_exp(Writer *writer,
+                                                 const FormatSection &to_conv) {
   if (to_conv.length_modifier == LengthModifier::L) {
     fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
     fputil::FPBits<long double> float_bits(float_raw);
diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index eb94f7541823ca..25fe57f02fbd70 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -293,7 +293,9 @@ template <typename ArgProvider> class Parser {
     return section;
   }
 
-  LIBC_PRINTF_SPLIT_DECL void write_float_arg_val(FormatSection &section, LengthModifier lm, size_t conv_index);
+  LIBC_PRINTF_SPLIT_DECL void write_float_arg_val(FormatSection &section,
+                                                  LengthModifier lm,
+                                                  size_t conv_index);
   LIBC_PRINTF_SPLIT_DECL TypeDesc float_type_desc(LengthModifier lm);
   LIBC_PRINTF_SPLIT_DECL bool advance_arg_if_float(TypeDesc cur_type_desc);
 
@@ -701,9 +703,9 @@ template <typename ArgParser>
 LIBC_PRINTF_SPLIT_DEFN bool
 Parser<ArgParser>::advance_arg_if_float(TypeDesc cur_type_desc) {
   if (cur_type_desc == type_desc_from_type<double>())
-      args_cur.template next_var<double>();
+    args_cur.template next_var<double>();
   else if (cur_type_desc == type_desc_from_type<long double>())
-      args_cur.template next_var<long double>();
+    args_cur.template next_var<long double>();
   else
     return false;
   return true;



More information about the libc-commits mailing list