-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[libc] Modular printf option (float only) #147426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/mysterymath/modular-printf/clang
Are you sure you want to change the base?
[libc] Modular printf option (float only) #147426
Conversation
@llvm/pr-subscribers-libc Author: Daniel Thornburgh (mysterymath) ChangesThis adds LIBC_CONF_PRINTF_MODULAR, which causes floating point support (later, others) to be weakly linked into the implementation. __printf_modular becomes the main entry point of the implementaiton, an printf itself wraps __printf_modular. printf it also contains a BFD_RELOC_NONE relocation to bring in the float aspect. See issue #146159 for context. Full diff: https://github.com/llvm/llvm-project/pull/147426.diff 14 Files Affected:
diff --git a/libc/config/config.json b/libc/config/config.json
index d53b2936edb07..4278169cd5940 100644
--- a/libc/config/config.json
+++ b/libc/config/config.json
@@ -45,6 +45,10 @@
"LIBC_CONF_PRINTF_RUNTIME_DISPATCH": {
"value": true,
"doc": "Use dynamic dispatch for the output mechanism to reduce code size."
+ },
+ "LIBC_CONF_PRINTF_MODULAR": {
+ "value": true,
+ "doc": "Split printf implementation into modules that can be lazily linked in."
}
},
"scanf": {
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index 109412225634f..1998c067dc77a 100644
--- a/libc/docs/configure.rst
+++ b/libc/docs/configure.rst
@@ -45,6 +45,7 @@ to learn about the defaults for your platform and target.
- ``LIBC_CONF_PRINTF_FLOAT_TO_STR_USE_DYADIC_FLOAT``: Use dyadic float for faster and smaller but less accurate printf doubles.
- ``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_MODULAR``: Split printf implementation into modules that can be lazily linked in.
- ``LIBC_CONF_PRINTF_RUNTIME_DISPATCH``: Use dynamic dispatch for the output mechanism to reduce code size.
* **"pthread" options**
- ``LIBC_CONF_RAW_MUTEX_DEFAULT_SPIN_COUNT``: Default number of spins before blocking if a mutex is in contention (default to 100).
diff --git a/libc/src/stdio/generic/CMakeLists.txt b/libc/src/stdio/generic/CMakeLists.txt
index 6361822b61999..41b18bc7195ca 100644
--- a/libc/src/stdio/generic/CMakeLists.txt
+++ b/libc/src/stdio/generic/CMakeLists.txt
@@ -412,10 +412,15 @@ if(LLVM_LIBC_FULL_BUILD)
)
endif()
+set(printf_srcs printf.cpp)
+if (LIBC_CONF_PRINTF_MODULAR)
+ list(APPEND printf_srcs printf_modular.cpp)
+endif()
+
add_generic_entrypoint_object(
printf
SRCS
- printf.cpp
+ ${printf_srcs}
HDRS
../printf.h
DEPENDS
diff --git a/libc/src/stdio/generic/printf_modular.cpp b/libc/src/stdio/generic/printf_modular.cpp
new file mode 100644
index 0000000000000..3a6a580002062
--- /dev/null
+++ b/libc/src/stdio/generic/printf_modular.cpp
@@ -0,0 +1,40 @@
+//===-- Implementation of printf_modular-----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/printf.h"
+
+#include "src/__support/File/file.h"
+#include "src/__support/arg_list.h"
+#include "src/__support/macros/config.h"
+#include "src/stdio/printf_core/vfprintf_internal.h"
+
+#include "hdr/types/FILE.h"
+#include <stdarg.h>
+
+#ifndef LIBC_COPT_STDIO_USE_SYSTEM_FILE
+#define PRINTF_STDOUT LIBC_NAMESPACE::stdout
+#else // LIBC_COPT_STDIO_USE_SYSTEM_FILE
+#define PRINTF_STDOUT ::stdout
+#endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, __printf_modular,
+ (const char *__restrict format, ...)) {
+ va_list vlist;
+ va_start(vlist, format);
+ internal::ArgList args(vlist); // This holder class allows for easier copying
+ // and pointer semantics, as well as handling
+ // destruction automatically.
+ va_end(vlist);
+ int ret_val = printf_core::vfprintf_internal_modular(
+ reinterpret_cast<::FILE *>(PRINTF_STDOUT), format, args);
+ return ret_val;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/printf.h b/libc/src/stdio/printf.h
index 9e47ad8680f9c..81b7d866a6a59 100644
--- a/libc/src/stdio/printf.h
+++ b/libc/src/stdio/printf.h
@@ -15,6 +15,7 @@
namespace LIBC_NAMESPACE_DECL {
int printf(const char *__restrict format, ...);
+int __printf_modular(const char *__restrict format, ...);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index c22f9858f3b1e..abc4cc8269d79 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -28,6 +28,9 @@ endif()
if(LIBC_CONF_PRINTF_RUNTIME_DISPATCH)
list(APPEND printf_config_copts "-DLIBC_COPT_PRINTF_RUNTIME_DISPATCH")
endif()
+if(LIBC_CONF_PRINTF_MODULAR)
+ list(APPEND printf_config_copts "-DLIBC_COPT_PRINTF_MODULAR")
+endif()
if(printf_config_copts)
list(PREPEND printf_config_copts "COMPILE_OPTIONS")
endif()
@@ -112,10 +115,12 @@ add_header_library(
libc.src.__support.StringUtil.error_to_string
)
-add_header_library(
+add_object_library(
printf_main
HDRS
printf_main.h
+ SRCS
+ float_impl.cpp
DEPENDS
.parser
.converter
diff --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h
index ed004f9a26a13..deeb566bd4092 100644
--- a/libc/src/stdio/printf_core/float_dec_converter.h
+++ b/libc/src/stdio/printf_core/float_dec_converter.h
@@ -1122,11 +1122,23 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer<write_mode> *writer,
}
}
+template <WriteMode write_mode>
+LIBC_PRINTF_MODULAR_DECL int
+convert_float_decimal(Writer<write_mode> *writer, const FormatSection &to_conv);
+template <WriteMode write_mode>
+LIBC_PRINTF_MODULAR_DECL int
+convert_float_dec_exp(Writer<write_mode> *writer, const FormatSection &to_conv);
+template <WriteMode write_mode>
+LIBC_PRINTF_MODULAR_DECL int
+convert_float_dec_auto(Writer<write_mode> *writer,
+ const FormatSection &to_conv);
+
+#ifdef LIBC_PRINTF_DEFINE_MODULAR
// TODO: unify the float converters to remove the duplicated checks for inf/nan.
template <WriteMode write_mode>
-LIBC_INLINE int convert_float_decimal(Writer<write_mode> *writer,
- const FormatSection &to_conv) {
+int convert_float_decimal(Writer<write_mode> *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);
@@ -1147,8 +1159,8 @@ LIBC_INLINE int convert_float_decimal(Writer<write_mode> *writer,
}
template <WriteMode write_mode>
-LIBC_INLINE int convert_float_dec_exp(Writer<write_mode> *writer,
- const FormatSection &to_conv) {
+int convert_float_dec_exp(Writer<write_mode> *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,8 +1181,8 @@ LIBC_INLINE int convert_float_dec_exp(Writer<write_mode> *writer,
}
template <WriteMode write_mode>
-LIBC_INLINE int convert_float_dec_auto(Writer<write_mode> *writer,
- const FormatSection &to_conv) {
+int convert_float_dec_auto(Writer<write_mode> *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);
@@ -1189,6 +1201,7 @@ LIBC_INLINE int convert_float_dec_auto(Writer<write_mode> *writer,
return convert_inf_nan(writer, to_conv);
}
+#endif
} // namespace printf_core
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/printf_core/float_dec_converter_limited.h b/libc/src/stdio/printf_core/float_dec_converter_limited.h
index f468dbc8e2ae8..9804a38964be0 100644
--- a/libc/src/stdio/printf_core/float_dec_converter_limited.h
+++ b/libc/src/stdio/printf_core/float_dec_converter_limited.h
@@ -676,22 +676,34 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer<write_mode> *writer,
}
template <WriteMode write_mode>
-LIBC_INLINE int convert_float_decimal(Writer<write_mode> *writer,
- const FormatSection &to_conv) {
+LIBC_PRINTF_MODULAR_DECL int convert_float_decimal(Writer<write_mode> *writer,
+ const FormatSection &to_conv);
+template <WriteMode write_mode>
+LIBC_PRINTF_MODULAR_DECL int convert_float_dec_exp(Writer<write_mode> *writer,
+ const FormatSection &to_conv);
+template <WriteMode write_mode>
+LIBC_PRINTF_MODULAR_DECL int convert_float_dec_auto(Writer<write_mode> *writer,
+ const FormatSection &to_conv);
+
+#ifdef LIBC_PRINTF_DEFINE_MODULAR
+template <WriteMode write_mode>
+int convert_float_decimal(Writer<write_mode> *writer,
+ const FormatSection &to_conv) {
return convert_float_outer(writer, to_conv, ConversionType::F);
}
template <WriteMode write_mode>
-LIBC_INLINE int convert_float_dec_exp(Writer<write_mode> *writer,
- const FormatSection &to_conv) {
+int convert_float_dec_exp(Writer<write_mode> *writer,
+ const FormatSection &to_conv) {
return convert_float_outer(writer, to_conv, ConversionType::E);
}
template <WriteMode write_mode>
-LIBC_INLINE int convert_float_dec_auto(Writer<write_mode> *writer,
- const FormatSection &to_conv) {
+int convert_float_dec_auto(Writer<write_mode> *writer,
+ const FormatSection &to_conv) {
return convert_float_outer(writer, to_conv, ConversionType::G);
}
+#endif
} // namespace printf_core
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/printf_core/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h
index 16592e7bac932..fa724066813d7 100644
--- a/libc/src/stdio/printf_core/float_hex_converter.h
+++ b/libc/src/stdio/printf_core/float_hex_converter.h
@@ -26,8 +26,13 @@ namespace LIBC_NAMESPACE_DECL {
namespace printf_core {
template <WriteMode write_mode>
-LIBC_INLINE int convert_float_hex_exp(Writer<write_mode> *writer,
- const FormatSection &to_conv) {
+LIBC_PRINTF_MODULAR_DECL int convert_float_hex_exp(Writer<write_mode> *writer,
+ const FormatSection &to_conv);
+
+#ifdef LIBC_PRINTF_DEFINE_MODULAR
+template <WriteMode write_mode>
+int convert_float_hex_exp(Writer<write_mode> *writer,
+ const FormatSection &to_conv) {
using LDBits = fputil::FPBits<long double>;
using StorageType = LDBits::StorageType;
@@ -254,6 +259,7 @@ LIBC_INLINE int convert_float_hex_exp(Writer<write_mode> *writer,
}
return WRITE_OK;
}
+#endif
} // namespace printf_core
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/printf_core/float_impl.cpp b/libc/src/stdio/printf_core/float_impl.cpp
new file mode 100644
index 0000000000000..e7c9ba39aa148
--- /dev/null
+++ b/libc/src/stdio/printf_core/float_impl.cpp
@@ -0,0 +1,41 @@
+#ifdef LIBC_COPT_PRINTF_MODULAR
+#include "src/__support/arg_list.h"
+
+#define LIBC_PRINTF_DEFINE_MODULAR
+#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"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace printf_core {
+template class Parser<internal::ArgList>;
+template class Parser<internal::DummyArgList<false>>;
+template class Parser<internal::DummyArgList<true>>;
+template class Parser<internal::StructArgList<false>>;
+template class Parser<internal::StructArgList<true>>;
+
+#define INSTANTIATE_CONVERT_FN(NAME) \
+ template int NAME<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>( \
+ Writer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> * writer, \
+ const FormatSection &to_conv); \
+ template int NAME<WriteMode::FLUSH_TO_STREAM>( \
+ Writer<WriteMode::FLUSH_TO_STREAM> * writer, \
+ const FormatSection &to_conv); \
+ template int NAME<WriteMode::RESIZE_AND_FILL_BUFF>( \
+ Writer<WriteMode::RESIZE_AND_FILL_BUFF> * writer, \
+ const FormatSection &to_conv); \
+ template int NAME<WriteMode::RUNTIME_DISPATCH>( \
+ Writer<WriteMode::RUNTIME_DISPATCH> * writer, \
+ const FormatSection &to_conv)
+
+INSTANTIATE_CONVERT_FN(convert_float_decimal);
+INSTANTIATE_CONVERT_FN(convert_float_dec_exp);
+INSTANTIATE_CONVERT_FN(convert_float_dec_auto);
+INSTANTIATE_CONVERT_FN(convert_float_hex_exp);
+
+} // namespace printf_core
+} // namespace LIBC_NAMESPACE_DECL
+
+// Bring this file into the link if __printf_float is referenced.
+extern "C" void __printf_float() {}
+#endif
diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index cef9b1ae58fa0..5a1eea36b603f 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -236,11 +236,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
@@ -299,6 +295,12 @@ template <typename ArgProvider> class Parser {
return section;
}
+ LIBC_PRINTF_MODULAR_DECL void write_float_arg_val(FormatSection §ion,
+ LengthModifier lm,
+ size_t conv_index);
+ LIBC_PRINTF_MODULAR_DECL TypeDesc float_type_desc(LengthModifier lm);
+ LIBC_PRINTF_MODULAR_DECL bool advance_arg_if_float(TypeDesc cur_type_desc);
+
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
@@ -474,10 +476,9 @@ 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 (&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
// Floating point numbers may be stored separately from the other
@@ -630,10 +631,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>();
+ conv_size = float_type_desc(lm);
break;
#endif // LIBC_COPT_PRINTF_DISABLE_FLOAT
#ifdef LIBC_INTERNAL_PRINTF_HAS_FIXED_POINT
@@ -682,6 +680,38 @@ template <typename ArgProvider> class Parser {
#endif // LIBC_COPT_PRINTF_DISABLE_INDEX_MODE
};
+#ifdef LIBC_PRINTF_DEFINE_MODULAR
+template <typename ArgParser>
+void Parser<ArgParser>::write_float_arg_val(FormatSection §ion,
+ 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>
+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>();
+}
+
+template <typename ArgParser>
+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
} // 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 8a48abdd170ec..8f6ae8b41bc92 100644
--- a/libc/src/stdio/printf_core/printf_config.h
+++ b/libc/src/stdio/printf_core/printf_config.h
@@ -48,4 +48,11 @@
// LIBC_COPT_PRINTF_NO_NULLPTR_CHECKS
+#ifdef LIBC_COPT_PRINTF_MODULAR
+#define LIBC_PRINTF_MODULAR_DECL [[gnu::weak]]
+#else
+#define LIBC_PRINTF_MODULAR_DECL LIBC_INLINE
+#define LIBC_PRINTF_DEFINE_MODULAR
+#endif
+
#endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_PRINTF_CONFIG_H
diff --git a/libc/src/stdio/printf_core/printf_main.h b/libc/src/stdio/printf_core/printf_main.h
index 57f29858d5298..c77922bb4f044 100644
--- a/libc/src/stdio/printf_core/printf_main.h
+++ b/libc/src/stdio/printf_core/printf_main.h
@@ -22,8 +22,8 @@ namespace LIBC_NAMESPACE_DECL {
namespace printf_core {
template <WriteMode write_mode>
-int printf_main(Writer<write_mode> *writer, const char *__restrict str,
- internal::ArgList &args) {
+int printf_main_modular(Writer<write_mode> *writer, const char *__restrict str,
+ internal::ArgList &args) {
Parser<internal::ArgList> parser(str, args);
int result = 0;
for (FormatSection cur_section = parser.get_next_section();
@@ -41,6 +41,15 @@ int printf_main(Writer<write_mode> *writer, const char *__restrict str,
return writer->get_chars_written();
}
+template <WriteMode write_mode>
+int printf_main(Writer<write_mode> *writer, const char *__restrict str,
+ internal::ArgList &args) {
+#ifdef LIBC_COPT_PRINTF_MODULAR
+ __asm__ __volatile__ (".reloc ., BFD_RELOC_NONE, __printf_float");
+#endif
+ return printf_main_modular(writer, str, args);
+}
+
} // namespace printf_core
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/printf_core/vfprintf_internal.h b/libc/src/stdio/printf_core/vfprintf_internal.h
index 630de9d9d43dd..c9d6fce458409 100644
--- a/libc/src/stdio/printf_core/vfprintf_internal.h
+++ b/libc/src/stdio/printf_core/vfprintf_internal.h
@@ -67,7 +67,7 @@ LIBC_INLINE int file_write_hook(cpp::string_view new_str, void *fp) {
return WRITE_OK;
}
-LIBC_INLINE int vfprintf_internal(::FILE *__restrict stream,
+LIBC_INLINE int vfprintf_internal_modular(::FILE *__restrict stream,
const char *__restrict format,
internal::ArgList &args) {
constexpr size_t BUFF_SIZE = 1024;
@@ -76,7 +76,7 @@ LIBC_INLINE int vfprintf_internal(::FILE *__restrict stream,
buffer, BUFF_SIZE, &file_write_hook, reinterpret_cast<void *>(stream));
Writer writer(wb);
internal::flockfile(stream);
- int retval = printf_main(&writer, format, args);
+ int retval = printf_main_modular(&writer, format, args);
int flushval = wb.overflow_write("");
if (flushval != WRITE_OK)
retval = flushval;
@@ -84,6 +84,15 @@ LIBC_INLINE int vfprintf_internal(::FILE *__restrict stream,
return retval;
}
+LIBC_INLINE int vfprintf_internal(::FILE *__restrict stream,
+ const char *__restrict format,
+ internal::ArgList &args) {
+#ifdef LIBC_COPT_PRINTF_SPLIT
+ __asm__ __volatile__(".reloc ., BFD_RELOC_NONE, __printf_float");
+#endif
+ return vfprintf_internal_modular(stream, format, args);
+}
+
} // namespace printf_core
} // namespace LIBC_NAMESPACE_DECL
|
You can test this locally with the following command:git-clang-format --diff HEAD~1 HEAD --extensions cpp,h -- libc/src/stdio/generic/printf_modular.cpp libc/src/stdio/printf_core/float_impl.cpp libc/src/stdio/printf.h libc/src/stdio/printf_core/float_dec_converter.h libc/src/stdio/printf_core/float_dec_converter_limited.h libc/src/stdio/printf_core/float_hex_converter.h libc/src/stdio/printf_core/parser.h libc/src/stdio/printf_core/printf_config.h libc/src/stdio/printf_core/printf_main.h libc/src/stdio/printf_core/vfprintf_internal.h View the diff from clang-format here.diff --git a/libc/src/stdio/printf_core/float_dec_converter_limited.h b/libc/src/stdio/printf_core/float_dec_converter_limited.h
index d9af10dcc..ab2b8854a 100644
--- a/libc/src/stdio/printf_core/float_dec_converter_limited.h
+++ b/libc/src/stdio/printf_core/float_dec_converter_limited.h
@@ -676,14 +676,15 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer<write_mode> *writer,
}
template <WriteMode write_mode>
-LIBC_PRINTF_MODULAR_DECL int convert_float_decimal(Writer<write_mode> *writer,
- const FormatSection &to_conv);
+LIBC_PRINTF_MODULAR_DECL int
+convert_float_decimal(Writer<write_mode> *writer, const FormatSection &to_conv);
template <WriteMode write_mode>
-LIBC_PRINTF_MODULAR_DECL int convert_float_dec_exp(Writer<write_mode> *writer,
- const FormatSection &to_conv);
+LIBC_PRINTF_MODULAR_DECL int
+convert_float_dec_exp(Writer<write_mode> *writer, const FormatSection &to_conv);
template <WriteMode write_mode>
-LIBC_PRINTF_MODULAR_DECL int convert_float_dec_auto(Writer<write_mode> *writer,
- const FormatSection &to_conv);
+LIBC_PRINTF_MODULAR_DECL int
+convert_float_dec_auto(Writer<write_mode> *writer,
+ const FormatSection &to_conv);
#ifdef LIBC_PRINTF_DEFINE_MODULAR
template <WriteMode write_mode>
diff --git a/libc/src/stdio/printf_core/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h
index f1aa556fe..e462cce52 100644
--- a/libc/src/stdio/printf_core/float_hex_converter.h
+++ b/libc/src/stdio/printf_core/float_hex_converter.h
@@ -26,8 +26,8 @@ namespace LIBC_NAMESPACE_DECL {
namespace printf_core {
template <WriteMode write_mode>
-LIBC_PRINTF_MODULAR_DECL int convert_float_hex_exp(Writer<write_mode> *writer,
- const FormatSection &to_conv);
+LIBC_PRINTF_MODULAR_DECL int
+convert_float_hex_exp(Writer<write_mode> *writer, const FormatSection &to_conv);
#ifdef LIBC_PRINTF_DEFINE_MODULAR
template <WriteMode write_mode>
diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h
index f25e761fa..edc373b2b 100644
--- a/libc/src/stdio/printf_core/parser.h
+++ b/libc/src/stdio/printf_core/parser.h
@@ -296,8 +296,8 @@ public:
}
LIBC_PRINTF_MODULAR_DECL void write_float_arg_val(FormatSection §ion,
- LengthModifier lm,
- size_t conv_index);
+ LengthModifier lm,
+ size_t conv_index);
LIBC_PRINTF_MODULAR_DECL TypeDesc float_type_desc(LengthModifier lm);
LIBC_PRINTF_MODULAR_DECL bool advance_arg_if_float(TypeDesc cur_type_desc);
diff --git a/libc/src/stdio/printf_core/vfprintf_internal.h b/libc/src/stdio/printf_core/vfprintf_internal.h
index 921eea9e0..c68f14bbe 100644
--- a/libc/src/stdio/printf_core/vfprintf_internal.h
+++ b/libc/src/stdio/printf_core/vfprintf_internal.h
@@ -68,8 +68,8 @@ LIBC_INLINE int file_write_hook(cpp::string_view new_str, void *fp) {
}
LIBC_INLINE int vfprintf_internal_modular(::FILE *__restrict stream,
- const char *__restrict format,
- internal::ArgList &args) {
+ const char *__restrict format,
+ internal::ArgList &args) {
constexpr size_t BUFF_SIZE = 1024;
char buffer[BUFF_SIZE];
printf_core::WriteBuffer<Mode<WriteMode::FLUSH_TO_STREAM>::value> wb(
|
Sending a draft PR for this to get some early feedback. In particular, on the libc side, some things are missing:
Prev PR: #147431 |
42f5beb
to
8d93269
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't done a full scan yet, but do you think this would work fine for the GPU? We support weak symbols, but NVPTX doesn't handle extern weak
correctly. Beside that it's normal static linking semantics except it's all LTO.
2eedccf
to
215f1f9
Compare
8d93269
to
04943cc
Compare
If I understand what you mean by EDIT: I suppose that's not completely correct; I suppose you could include a weak definition that's just a byte or something in the module itself. It would get clobbered by the strongly-referenced real implementation aspect. But messy; is there a specific obstacle to |
Yes, ELF standard says that |
#define LIBC_PRINTF_DEFINE_MODULAR | ||
#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" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given this, do you need to modify converter.h
or converter_atlas.h
?
int printf_main(Writer<write_mode> *writer, const char *__restrict str, | ||
internal::ArgList &args) { | ||
#ifdef LIBC_COPT_PRINTF_MODULAR | ||
__asm__ __volatile__ (".reloc ., BFD_RELOC_NONE, __printf_float"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a way to do this with compiler attributes instead of asm?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not to my knowledge. We could probably create a clang builtin function that lowers to the new llvm.reloc.none
intrinsic created as part of this PR chain though; is there a reason to prefer that over inline ASM for cases like this?
@@ -1122,11 +1122,23 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer<write_mode> *writer, | |||
} | |||
} | |||
|
|||
template <WriteMode write_mode> | |||
LIBC_PRINTF_MODULAR_DECL int | |||
convert_float_decimal(Writer<write_mode> *writer, const FormatSection &to_conv); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be a separate PR, but can we change all the writer
argument to reference instead of pointer?
04943cc
to
028a89f
Compare
619dfb7
to
e77a856
Compare
028a89f
to
e6dd4bd
Compare
if (LIBC_CONF_PRINTF_MODULAR) | ||
list(APPEND printf_srcs printf_modular.cpp) | ||
endif() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it make sense to have __printf_float
as a separate entrypoint so that it can be controlled per-platform with the same mechanism as other entrypoints?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm understanding the idea correctly, this would allow platforms to control whether or not named aspects of the various format string function implementations are included in the libc build. This would only work with LIBC_CONF_PRINTF_MODULAR
, and it would cause link failures unless programs linked against that libc could be proven not to use those aspects. (Or maybe if they could be proven to use those aspects; that seems more useful. The difference would be whether or not the plain printf
definitions would refer to __printf_float
, for example.)
Is this roughly what you were thinking? I'm open to this, but it seems to add complexity, and it stretches the notion of entrypoint a bit. Do we do anything like this elsewhere?
e6dd4bd
to
68ff227
Compare
This adds LIBC_CONF_PRINTF_MODULAR, which causes floating point support (later, others) to be weakly linked into the implementation. __printf_modular becomes the main entry point of the implementaiton, an printf itself wraps __printf_modular. printf it also contains a BFD_RELOC_NONE relocation to bring in the float aspect. See issue #146159 for context.
e76aacc
to
0ff36e3
Compare
This adds LIBC_CONF_PRINTF_MODULAR, which causes floating point support (later, others) to be weakly linked into the implementation. __printf_modular becomes the main entry point of the implementaiton, an printf itself wraps __printf_modular. printf it also contains a BFD_RELOC_NONE relocation to bring in the float aspect.
See issue #146159 for context.