From 885d874655d9fb58a74b6c3ecec262278952953d Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:20:20 +0530 Subject: [PATCH 01/19] Initial moves --- libc/src/stdio/scanf_core/reader.cpp | 61 +++++++++++++++++++- libc/src/stdio/scanf_core/reader.h | 26 +-------- libc/src/stdio/scanf_core/vfscanf_internal.h | 2 +- 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/libc/src/stdio/scanf_core/reader.cpp b/libc/src/stdio/scanf_core/reader.cpp index ec1f5c098dc7a..cc09f47709d6b 100644 --- a/libc/src/stdio/scanf_core/reader.cpp +++ b/libc/src/stdio/scanf_core/reader.cpp @@ -10,9 +10,67 @@ #include "src/__support/macros/config.h" #include +#include "src/__support/File/file.h" + namespace LIBC_NAMESPACE_DECL { namespace scanf_core { +namespace internal { + +#if defined(LIBC_TARGET_ARCH_IS_GPU) +// The GPU build provides FILE access through the host operating system's +// library. So here we simply use the public entrypoints like in the SYSTEM_FILE +// interface. Entrypoints should normally not call others, this is an exception. +// FIXME: We do not acquire any locks here, so this is not thread safe. +LIBC_INLINE int getc(void *f) { + return LIBC_NAMESPACE::getc(reinterpret_cast<::FILE *>(f)); +} + +LIBC_INLINE void ungetc(int c, void *f) { + LIBC_NAMESPACE::ungetc(c, reinterpret_cast<::FILE *>(f)); +} + +#elif !defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) + +LIBC_INLINE int getc(void *f) { + unsigned char c; + auto result = + reinterpret_cast(f)->read_unlocked(&c, 1); + size_t r = result.value; + if (result.has_error() || r != 1) + return '\0'; + + return c; +} + +LIBC_INLINE void ungetc(int c, void *f) { + reinterpret_cast(f)->ungetc_unlocked(c); +} + +#else // defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) + +// Since ungetc_unlocked isn't always available, we don't acquire the lock for +// system files. +LIBC_INLINE int getc(void *f) { return ::getc(reinterpret_cast<::FILE *>(f)); } + +LIBC_INLINE void ungetc(int c, void *f) { + ::ungetc(c, reinterpret_cast<::FILE *>(f)); +} +#endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE + +} // namespace internal + +char Reader::getc() { + ++cur_chars_read; + if (rb != nullptr) { + char output = rb->buffer[rb->buff_cur]; + ++(rb->buff_cur); + return output; + } + // This should reset the buffer if applicable. + return static_cast(internal::getc(input_stream)); +} + void Reader::ungetc(char c) { --cur_chars_read; if (rb != nullptr && rb->buff_cur > 0) { @@ -23,7 +81,8 @@ void Reader::ungetc(char c) { --(rb->buff_cur); return; } - stream_ungetc(static_cast(c), input_stream); + internal::ungetc(static_cast(c), input_stream); } + } // namespace scanf_core } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/scanf_core/reader.h b/libc/src/stdio/scanf_core/reader.h index f984fd9378910..e29ea6ea7d891 100644 --- a/libc/src/stdio/scanf_core/reader.h +++ b/libc/src/stdio/scanf_core/reader.h @@ -16,9 +16,6 @@ namespace LIBC_NAMESPACE_DECL { namespace scanf_core { -using StreamGetc = int (*)(void *); -using StreamUngetc = void (*)(int, void *); - // This is intended to be either a raw string or a buffer syncronized with the // file's internal buffer. struct ReadBuffer { @@ -29,38 +26,21 @@ struct ReadBuffer { class Reader { ReadBuffer *rb; - void *input_stream = nullptr; - - // TODO: Remove these unnecessary function pointers - StreamGetc stream_getc = nullptr; - StreamUngetc stream_ungetc = nullptr; - size_t cur_chars_read = 0; public: // TODO: Set buff_len with a proper constant LIBC_INLINE Reader(ReadBuffer *string_buffer) : rb(string_buffer) {} - LIBC_INLINE Reader(void *stream, StreamGetc stream_getc_in, - StreamUngetc stream_ungetc_in, + LIBC_INLINE Reader(void *stream, ReadBuffer *stream_buffer = nullptr) - : rb(stream_buffer), input_stream(stream), stream_getc(stream_getc_in), - stream_ungetc(stream_ungetc_in) {} + : rb(stream_buffer), input_stream(stream){} // This returns the next character from the input and advances it by one // character. When it hits the end of the string or file it returns '\0' to // signal to stop parsing. - LIBC_INLINE char getc() { - ++cur_chars_read; - if (rb != nullptr) { - char output = rb->buffer[rb->buff_cur]; - ++(rb->buff_cur); - return output; - } - // This should reset the buffer if applicable. - return static_cast(stream_getc(input_stream)); - } + char getc(); // This moves the input back by one character, placing c into the buffer if // this is a file reader, else c is ignored. diff --git a/libc/src/stdio/scanf_core/vfscanf_internal.h b/libc/src/stdio/scanf_core/vfscanf_internal.h index 67126431fcded..c96c672bc6fac 100644 --- a/libc/src/stdio/scanf_core/vfscanf_internal.h +++ b/libc/src/stdio/scanf_core/vfscanf_internal.h @@ -103,7 +103,7 @@ LIBC_INLINE int vfscanf_internal(::FILE *__restrict stream, const char *__restrict format, internal::ArgList &args) { internal::flockfile(stream); - scanf_core::Reader reader(stream, &internal::getc, internal::ungetc); + scanf_core::Reader reader(stream); int retval = scanf_core::scanf_main(&reader, format, args); if (retval == 0 && internal::ferror_unlocked(stream)) retval = EOF; From 12f2ae071b882e25d47b635579583dbcf3886e22 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 27 Dec 2024 21:47:08 +0530 Subject: [PATCH 02/19] Remove duplicate definition --- libc/src/stdio/scanf_core/vfscanf_internal.h | 29 -------------------- 1 file changed, 29 deletions(-) diff --git a/libc/src/stdio/scanf_core/vfscanf_internal.h b/libc/src/stdio/scanf_core/vfscanf_internal.h index c96c672bc6fac..84d074711b8fb 100644 --- a/libc/src/stdio/scanf_core/vfscanf_internal.h +++ b/libc/src/stdio/scanf_core/vfscanf_internal.h @@ -38,14 +38,6 @@ LIBC_INLINE void flockfile(::FILE *) { return; } LIBC_INLINE void funlockfile(::FILE *) { return; } -LIBC_INLINE int getc(void *f) { - return LIBC_NAMESPACE::getc(reinterpret_cast<::FILE *>(f)); -} - -LIBC_INLINE void ungetc(int c, void *f) { - LIBC_NAMESPACE::ungetc(c, reinterpret_cast<::FILE *>(f)); -} - LIBC_INLINE int ferror_unlocked(::FILE *f) { return LIBC_NAMESPACE::ferror(f); } #elif !defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) @@ -58,21 +50,6 @@ LIBC_INLINE void funlockfile(FILE *f) { reinterpret_cast(f)->unlock(); } -LIBC_INLINE int getc(void *f) { - unsigned char c; - auto result = - reinterpret_cast(f)->read_unlocked(&c, 1); - size_t r = result.value; - if (result.has_error() || r != 1) - return '\0'; - - return c; -} - -LIBC_INLINE void ungetc(int c, void *f) { - reinterpret_cast(f)->ungetc_unlocked(c); -} - LIBC_INLINE int ferror_unlocked(FILE *f) { return reinterpret_cast(f)->error_unlocked(); } @@ -85,12 +62,6 @@ LIBC_INLINE void flockfile(::FILE *) { return; } LIBC_INLINE void funlockfile(::FILE *) { return; } -LIBC_INLINE int getc(void *f) { return ::getc(reinterpret_cast<::FILE *>(f)); } - -LIBC_INLINE void ungetc(int c, void *f) { - ::ungetc(c, reinterpret_cast<::FILE *>(f)); -} - LIBC_INLINE int ferror_unlocked(::FILE *f) { return ::ferror(f); } #endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE From 6236e59ed06eb4e333533a092a423372e9f8d6e1 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 27 Dec 2024 21:52:04 +0530 Subject: [PATCH 03/19] Doesn't build but should in CI --- libc/src/stdio/scanf_core/reader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libc/src/stdio/scanf_core/reader.cpp b/libc/src/stdio/scanf_core/reader.cpp index cc09f47709d6b..ccfcd220e19c2 100644 --- a/libc/src/stdio/scanf_core/reader.cpp +++ b/libc/src/stdio/scanf_core/reader.cpp @@ -6,11 +6,15 @@ // //===----------------------------------------------------------------------===// +#include "hdr/types/FILE.h" #include "src/stdio/scanf_core/reader.h" #include "src/__support/macros/config.h" +#include "src/__support/File/file.h" + #include -#include "src/__support/File/file.h" + + namespace LIBC_NAMESPACE_DECL { namespace scanf_core { From f3b8d7f06befde1a7a3f6aa7e7e506a40334bcfb Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 27 Dec 2024 22:05:53 +0530 Subject: [PATCH 04/19] clang-format patch --- libc/src/stdio/scanf_core/reader.cpp | 9 +++------ libc/src/stdio/scanf_core/reader.h | 7 +++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/libc/src/stdio/scanf_core/reader.cpp b/libc/src/stdio/scanf_core/reader.cpp index ccfcd220e19c2..e2dcdd5e1e05a 100644 --- a/libc/src/stdio/scanf_core/reader.cpp +++ b/libc/src/stdio/scanf_core/reader.cpp @@ -6,16 +6,13 @@ // //===----------------------------------------------------------------------===// -#include "hdr/types/FILE.h" #include "src/stdio/scanf_core/reader.h" -#include "src/__support/macros/config.h" +#include "hdr/types/FILE.h" #include "src/__support/File/file.h" +#include "src/__support/macros/config.h" #include - - - namespace LIBC_NAMESPACE_DECL { namespace scanf_core { @@ -51,7 +48,7 @@ LIBC_INLINE void ungetc(int c, void *f) { reinterpret_cast(f)->ungetc_unlocked(c); } -#else // defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) +#else // defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) // Since ungetc_unlocked isn't always available, we don't acquire the lock for // system files. diff --git a/libc/src/stdio/scanf_core/reader.h b/libc/src/stdio/scanf_core/reader.h index e29ea6ea7d891..c8b113b615795 100644 --- a/libc/src/stdio/scanf_core/reader.h +++ b/libc/src/stdio/scanf_core/reader.h @@ -33,14 +33,13 @@ class Reader { // TODO: Set buff_len with a proper constant LIBC_INLINE Reader(ReadBuffer *string_buffer) : rb(string_buffer) {} - LIBC_INLINE Reader(void *stream, - ReadBuffer *stream_buffer = nullptr) - : rb(stream_buffer), input_stream(stream){} + LIBC_INLINE Reader(void *stream, ReadBuffer *stream_buffer = nullptr) + : rb(stream_buffer), input_stream(stream) {} // This returns the next character from the input and advances it by one // character. When it hits the end of the string or file it returns '\0' to // signal to stop parsing. - char getc(); + char getc(); // This moves the input back by one character, placing c into the buffer if // this is a file reader, else c is ignored. From bfe6b86d3547c25346d5dd2faca1a2677489ca70 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 27 Dec 2024 22:33:40 +0530 Subject: [PATCH 05/19] Put overlay include last --- libc/src/stdio/scanf_core/reader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libc/src/stdio/scanf_core/reader.cpp b/libc/src/stdio/scanf_core/reader.cpp index e2dcdd5e1e05a..680c3b768f5d9 100644 --- a/libc/src/stdio/scanf_core/reader.cpp +++ b/libc/src/stdio/scanf_core/reader.cpp @@ -7,10 +7,11 @@ //===----------------------------------------------------------------------===// #include "src/stdio/scanf_core/reader.h" -#include "hdr/types/FILE.h" #include "src/__support/File/file.h" #include "src/__support/macros/config.h" +#include "hdr/types/FILE.h" + #include namespace LIBC_NAMESPACE_DECL { From 1f9e27cfc8596057212a67713045f678f61cada6 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 28 Dec 2024 20:11:20 +0530 Subject: [PATCH 06/19] Attempt to fix linker error From: https://github.com/llvm/llvm-project/actions/runs/12518682283/job/34921546556?pr=121215 Error was: ``` /usr/bin/ld: libc/src/stdio/scanf_core/CMakeFiles/libc.src.stdio.scanf_core.reader.dir/./reader.cpp.o: in function `__llvm_libc_20_0_0_git::scanf_core::Reader::getc()': reader.cpp:(.text._ZN22__llvm_libc_20_0_0_git10scanf_core6Reader4getcEv+0x38): undefined reference to `__llvm_libc_20_0_0_git::File::read_unlocked(void*, unsigned long)' /usr/bin/ld: libc/src/stdio/scanf_core/CMakeFiles/libc.src.stdio.scanf_core.reader.dir/./reader.cpp.o: in function `__llvm_libc_20_0_0_git::scanf_core::Reader::ungetc(char)': reader.cpp:(.text._ZN22__llvm_libc_20_0_0_git10scanf_core6Reader6ungetcEc+0x2c): undefined reference to `__llvm_libc_20_0_0_git::File::ungetc_unlocked(int)' /usr/bin/ld: libc/test/src/stdio/libc.test.src.stdio.sscanf_test.__unit__.__build__: hidden symbol `_ZN22__llvm_libc_20_0_0_git4File13read_unlockedEPvm' isn't defined /usr/bin/ld: final link failed: bad value clang++: error: linker command failed with exit code 1 (use -v to see invocation) ``` --- libc/src/stdio/scanf_core/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt index a8935d464417c..8016ac4ec7c58 100644 --- a/libc/src/stdio/scanf_core/CMakeLists.txt +++ b/libc/src/stdio/scanf_core/CMakeLists.txt @@ -62,6 +62,7 @@ add_object_library( reader.h DEPENDS libc.src.__support.macros.attributes + libc.hdr.types.FILE ) add_object_library( From 0abb5c3a69d9d8d4045ada78172045f387e977af Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 28 Dec 2024 22:34:15 +0530 Subject: [PATCH 07/19] try reorder --- libc/src/stdio/scanf_core/reader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libc/src/stdio/scanf_core/reader.cpp b/libc/src/stdio/scanf_core/reader.cpp index 680c3b768f5d9..e8ccf000bd453 100644 --- a/libc/src/stdio/scanf_core/reader.cpp +++ b/libc/src/stdio/scanf_core/reader.cpp @@ -7,13 +7,13 @@ //===----------------------------------------------------------------------===// #include "src/stdio/scanf_core/reader.h" -#include "src/__support/File/file.h" #include "src/__support/macros/config.h" -#include "hdr/types/FILE.h" - #include +#include "src/__support/File/file.h" +#include "hdr/types/FILE.h" + namespace LIBC_NAMESPACE_DECL { namespace scanf_core { From 13f418d3e449d199fabec1ffe545dc6e0f2a12c7 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Tue, 7 Jan 2025 20:50:53 -0500 Subject: [PATCH 08/19] Move getc back to header --- libc/src/stdio/scanf_core/reader.cpp | 11 ----------- libc/src/stdio/scanf_core/reader.h | 11 ++++++++++- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/libc/src/stdio/scanf_core/reader.cpp b/libc/src/stdio/scanf_core/reader.cpp index e8ccf000bd453..6de47779e5d19 100644 --- a/libc/src/stdio/scanf_core/reader.cpp +++ b/libc/src/stdio/scanf_core/reader.cpp @@ -62,17 +62,6 @@ LIBC_INLINE void ungetc(int c, void *f) { } // namespace internal -char Reader::getc() { - ++cur_chars_read; - if (rb != nullptr) { - char output = rb->buffer[rb->buff_cur]; - ++(rb->buff_cur); - return output; - } - // This should reset the buffer if applicable. - return static_cast(internal::getc(input_stream)); -} - void Reader::ungetc(char c) { --cur_chars_read; if (rb != nullptr && rb->buff_cur > 0) { diff --git a/libc/src/stdio/scanf_core/reader.h b/libc/src/stdio/scanf_core/reader.h index c8b113b615795..79972fb247021 100644 --- a/libc/src/stdio/scanf_core/reader.h +++ b/libc/src/stdio/scanf_core/reader.h @@ -39,7 +39,16 @@ class Reader { // This returns the next character from the input and advances it by one // character. When it hits the end of the string or file it returns '\0' to // signal to stop parsing. - char getc(); + LIBC_INLINE char getc() { + ++cur_chars_read; + if (rb != nullptr) { + char output = rb->buffer[rb->buff_cur]; + ++(rb->buff_cur); + return output; + } + // This should reset the buffer if applicable. + return static_cast(internal::getc(input_stream)); + } // This moves the input back by one character, placing c into the buffer if // this is a file reader, else c is ignored. From fe6f638eb7e935b5eb424dee2f1c30dee56460af Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Mon, 13 Jan 2025 19:17:00 -0500 Subject: [PATCH 09/19] WIP ??? --- libc/src/stdio/scanf_core/CMakeLists.txt | 30 ++++++++++ libc/src/stdio/scanf_core/reader.cpp | 64 ++------------------ libc/src/stdio/scanf_core/reader.h | 74 +++++++++++++++++++++++- 3 files changed, 107 insertions(+), 61 deletions(-) diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt index 8016ac4ec7c58..d646f3777d9d3 100644 --- a/libc/src/stdio/scanf_core/CMakeLists.txt +++ b/libc/src/stdio/scanf_core/CMakeLists.txt @@ -54,6 +54,32 @@ add_object_library( libc.src.__support.arg_list ) +if(LIBC_TARGET_OS_IS_GPU) +# TODO: fix this +add_object_library( + reader + SRCS + reader.cpp + HDRS + reader.h + DEPENDS + libc.src.__support.macros.attributes + libc.src.stdio.getc + libc.src.stdio.ungetc +) +elseif(NOT (TARGET libc.src.__support.File.file) ) +add_object_library( + reader + SRCS + reader.cpp + HDRS + reader.h + DEPENDS + libc.src.__support.macros.attributes + libc.hdr.types.FILE + ${use_system_file} +) +elseif((LLVM_LIBC_FULL_BUILD)) add_object_library( reader SRCS @@ -62,9 +88,13 @@ add_object_library( reader.h DEPENDS libc.src.__support.macros.attributes + libc.src.__support.File.file libc.hdr.types.FILE + ${use_system_file} ) +endif() + add_object_library( converter SRCS diff --git a/libc/src/stdio/scanf_core/reader.cpp b/libc/src/stdio/scanf_core/reader.cpp index 6de47779e5d19..13bac24838b72 100644 --- a/libc/src/stdio/scanf_core/reader.cpp +++ b/libc/src/stdio/scanf_core/reader.cpp @@ -11,69 +11,13 @@ #include -#include "src/__support/File/file.h" -#include "hdr/types/FILE.h" +// TODO: only include one of these depending on build mode +// #include "hdr/types/FILE.h" +// #include "src/__support/File/file.h" + namespace LIBC_NAMESPACE_DECL { namespace scanf_core { -namespace internal { - -#if defined(LIBC_TARGET_ARCH_IS_GPU) -// The GPU build provides FILE access through the host operating system's -// library. So here we simply use the public entrypoints like in the SYSTEM_FILE -// interface. Entrypoints should normally not call others, this is an exception. -// FIXME: We do not acquire any locks here, so this is not thread safe. -LIBC_INLINE int getc(void *f) { - return LIBC_NAMESPACE::getc(reinterpret_cast<::FILE *>(f)); -} - -LIBC_INLINE void ungetc(int c, void *f) { - LIBC_NAMESPACE::ungetc(c, reinterpret_cast<::FILE *>(f)); -} - -#elif !defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) - -LIBC_INLINE int getc(void *f) { - unsigned char c; - auto result = - reinterpret_cast(f)->read_unlocked(&c, 1); - size_t r = result.value; - if (result.has_error() || r != 1) - return '\0'; - - return c; -} - -LIBC_INLINE void ungetc(int c, void *f) { - reinterpret_cast(f)->ungetc_unlocked(c); -} - -#else // defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) - -// Since ungetc_unlocked isn't always available, we don't acquire the lock for -// system files. -LIBC_INLINE int getc(void *f) { return ::getc(reinterpret_cast<::FILE *>(f)); } - -LIBC_INLINE void ungetc(int c, void *f) { - ::ungetc(c, reinterpret_cast<::FILE *>(f)); -} -#endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE - -} // namespace internal - -void Reader::ungetc(char c) { - --cur_chars_read; - if (rb != nullptr && rb->buff_cur > 0) { - // While technically c should be written back to the buffer, in scanf we - // always write the character that was already there. Additionally, the - // buffer is most likely to contain a string that isn't part of a file, - // which may not be writable. - --(rb->buff_cur); - return; - } - internal::ungetc(static_cast(c), input_stream); -} - } // namespace scanf_core } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/scanf_core/reader.h b/libc/src/stdio/scanf_core/reader.h index 79972fb247021..1b8d430379a9a 100644 --- a/libc/src/stdio/scanf_core/reader.h +++ b/libc/src/stdio/scanf_core/reader.h @@ -9,13 +9,74 @@ #ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H #define LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H +// has the macro subsitution failure +// #ifdef LIBC_FULL_BUILD +#include "src/__support/File/file.h" +// #endif + #include "src/__support/macros/attributes.h" // For LIBC_INLINE #include "src/__support/macros/config.h" #include +// includes stdio.h +#include "hdr/types/FILE.h" + + +#if !defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) + + +#endif + namespace LIBC_NAMESPACE_DECL { namespace scanf_core { + +namespace internal { + +#if defined(LIBC_TARGET_ARCH_IS_GPU) +// The GPU build provides FILE access through the host operating system's +// library. So here we simply use the public entrypoints like in the SYSTEM_FILE +// interface. Entrypoints should normally not call others, this is an exception. +// FIXME: We do not acquire any locks here, so this is not thread safe. +LIBC_INLINE int getc(void *f) { + return LIBC_NAMESPACE::getc(reinterpret_cast<::FILE *>(f)); +} + +LIBC_INLINE void ungetc(int c, void *f) { + LIBC_NAMESPACE::ungetc(c, reinterpret_cast<::FILE *>(f)); +} + +#elif !defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) + +LIBC_INLINE int getc(void *f) { + unsigned char c; + auto result = + reinterpret_cast(f)->read_unlocked(&c, 1); + size_t r = result.value; + if (result.has_error() || r != 1) + return '\0'; + + return c; +} + +LIBC_INLINE void ungetc(int c, void *f) { + reinterpret_cast(f)->ungetc_unlocked(c); +} + +#else // defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) + +// Since ungetc_unlocked isn't always available, we don't acquire the lock for +// system files. +LIBC_INLINE int getc(void *f) { return ::getc(reinterpret_cast<::FILE *>(f)); } + +LIBC_INLINE void ungetc(int c, void *f) { + ::ungetc(c, reinterpret_cast<::FILE *>(f)); +} +#endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE + +} // namespace internal + + // This is intended to be either a raw string or a buffer syncronized with the // file's internal buffer. struct ReadBuffer { @@ -52,7 +113,18 @@ class Reader { // This moves the input back by one character, placing c into the buffer if // this is a file reader, else c is ignored. - void ungetc(char c); + LIBC_INLINE void ungetc(char c) { + --cur_chars_read; + if (rb != nullptr && rb->buff_cur > 0) { + // While technically c should be written back to the buffer, in scanf we + // always write the character that was already there. Additionally, the + // buffer is most likely to contain a string that isn't part of a file, + // which may not be writable. + --(rb->buff_cur); + return; + } + internal::ungetc(static_cast(c), input_stream); + } LIBC_INLINE size_t chars_read() { return cur_chars_read; } }; From cbe1ab0631043d1257c5935c78afceb20d65a1c5 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 18 Jan 2025 18:43:12 -0500 Subject: [PATCH 10/19] it works with COMPILE_OPTIONS param --- libc/src/stdio/scanf_core/CMakeLists.txt | 16 +++++++++------- libc/src/stdio/scanf_core/reader.h | 3 +++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt index d646f3777d9d3..c85c223c9cbb9 100644 --- a/libc/src/stdio/scanf_core/CMakeLists.txt +++ b/libc/src/stdio/scanf_core/CMakeLists.txt @@ -56,10 +56,10 @@ add_object_library( if(LIBC_TARGET_OS_IS_GPU) # TODO: fix this -add_object_library( +add_header_library( reader - SRCS - reader.cpp + # SRCS + # reader.cpp HDRS reader.h DEPENDS @@ -68,15 +68,17 @@ add_object_library( libc.src.stdio.ungetc ) elseif(NOT (TARGET libc.src.__support.File.file) ) -add_object_library( +add_header_library( reader - SRCS - reader.cpp + # SRCS + # reader.cpp HDRS reader.h DEPENDS libc.src.__support.macros.attributes libc.hdr.types.FILE + libc.src.__support.File.file + COMPILE_OPTIONS ${use_system_file} ) elseif((LLVM_LIBC_FULL_BUILD)) @@ -90,7 +92,7 @@ add_object_library( libc.src.__support.macros.attributes libc.src.__support.File.file libc.hdr.types.FILE - ${use_system_file} + # ${use_system_file} ) endif() diff --git a/libc/src/stdio/scanf_core/reader.h b/libc/src/stdio/scanf_core/reader.h index 1b8d430379a9a..fc4659c6b0bc6 100644 --- a/libc/src/stdio/scanf_core/reader.h +++ b/libc/src/stdio/scanf_core/reader.h @@ -30,6 +30,9 @@ namespace LIBC_NAMESPACE_DECL { namespace scanf_core { +#ifdef LIBC_COPT_STDIO_USE_SYSTEM_FILE +#endif + namespace internal { From 09194c20c7542380aab4f15724675a3bc15a6d4d Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 18 Jan 2025 19:02:45 -0500 Subject: [PATCH 11/19] clean header file --- libc/src/stdio/scanf_core/reader.h | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/libc/src/stdio/scanf_core/reader.h b/libc/src/stdio/scanf_core/reader.h index fc4659c6b0bc6..8a826999882b1 100644 --- a/libc/src/stdio/scanf_core/reader.h +++ b/libc/src/stdio/scanf_core/reader.h @@ -9,31 +9,16 @@ #ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H #define LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H -// has the macro subsitution failure -// #ifdef LIBC_FULL_BUILD #include "src/__support/File/file.h" -// #endif - #include "src/__support/macros/attributes.h" // For LIBC_INLINE #include "src/__support/macros/config.h" -#include - -// includes stdio.h #include "hdr/types/FILE.h" +#include -#if !defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE) - - -#endif namespace LIBC_NAMESPACE_DECL { namespace scanf_core { - -#ifdef LIBC_COPT_STDIO_USE_SYSTEM_FILE -#endif - - namespace internal { #if defined(LIBC_TARGET_ARCH_IS_GPU) From a459d1178ed88cc396e84a2504f9a1117de7cceb Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 18 Jan 2025 19:04:00 -0500 Subject: [PATCH 12/19] use same logic as vfscanf_internal --- libc/src/stdio/scanf_core/CMakeLists.txt | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt index c85c223c9cbb9..1b61292301814 100644 --- a/libc/src/stdio/scanf_core/CMakeLists.txt +++ b/libc/src/stdio/scanf_core/CMakeLists.txt @@ -67,7 +67,7 @@ add_header_library( libc.src.stdio.getc libc.src.stdio.ungetc ) -elseif(NOT (TARGET libc.src.__support.File.file) ) +elseif( (TARGET libc.src.__support.File.file) OR (NOT LLVM_LIBC_FULL_BUILD) ) add_header_library( reader # SRCS @@ -81,20 +81,6 @@ add_header_library( COMPILE_OPTIONS ${use_system_file} ) -elseif((LLVM_LIBC_FULL_BUILD)) -add_object_library( - reader - SRCS - reader.cpp - HDRS - reader.h - DEPENDS - libc.src.__support.macros.attributes - libc.src.__support.File.file - libc.hdr.types.FILE - # ${use_system_file} -) - endif() add_object_library( From 6144b003223d2b706b7e416ff34399a40cab3ff0 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 18 Jan 2025 19:16:27 -0500 Subject: [PATCH 13/19] avoid name lookup ambiguity --- libc/src/stdio/scanf_core/reader.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libc/src/stdio/scanf_core/reader.h b/libc/src/stdio/scanf_core/reader.h index 8a826999882b1..71bb7f0f9b428 100644 --- a/libc/src/stdio/scanf_core/reader.h +++ b/libc/src/stdio/scanf_core/reader.h @@ -19,7 +19,11 @@ namespace LIBC_NAMESPACE_DECL { namespace scanf_core { -namespace internal { +// We use the name "reader_internal" over "internal" because +// "internal" causes name lookups in files that include the current header to be ambigious +// i.e. `internal::foo` in those files, will try to lookup in `LIBC_NAMESPACE::scanf_core::internal` over `LIBC_NAMESPACE::internal` +// for e.g., `internal::ArgList` in `libc/src/stdio/scanf_core/scanf_main.h` +namespace reader_internal { #if defined(LIBC_TARGET_ARCH_IS_GPU) // The GPU build provides FILE access through the host operating system's @@ -62,7 +66,7 @@ LIBC_INLINE void ungetc(int c, void *f) { } #endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE -} // namespace internal +} // namespace reader_internal // This is intended to be either a raw string or a buffer syncronized with the @@ -96,7 +100,7 @@ class Reader { return output; } // This should reset the buffer if applicable. - return static_cast(internal::getc(input_stream)); + return static_cast(reader_internal::getc(input_stream)); } // This moves the input back by one character, placing c into the buffer if @@ -111,7 +115,7 @@ class Reader { --(rb->buff_cur); return; } - internal::ungetc(static_cast(c), input_stream); + reader_internal::ungetc(static_cast(c), input_stream); } LIBC_INLINE size_t chars_read() { return cur_chars_read; } From 97ae0745861caf3fa6b7b2d7d4dc69f8ad647fc4 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 18 Jan 2025 19:47:27 -0500 Subject: [PATCH 14/19] clang-format patch --- libc/src/stdio/scanf_core/reader.cpp | 1 - libc/src/stdio/scanf_core/reader.h | 11 +++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/libc/src/stdio/scanf_core/reader.cpp b/libc/src/stdio/scanf_core/reader.cpp index 13bac24838b72..2c0bc17f6b2aa 100644 --- a/libc/src/stdio/scanf_core/reader.cpp +++ b/libc/src/stdio/scanf_core/reader.cpp @@ -15,7 +15,6 @@ // #include "hdr/types/FILE.h" // #include "src/__support/File/file.h" - namespace LIBC_NAMESPACE_DECL { namespace scanf_core { diff --git a/libc/src/stdio/scanf_core/reader.h b/libc/src/stdio/scanf_core/reader.h index 71bb7f0f9b428..a1a8314182da7 100644 --- a/libc/src/stdio/scanf_core/reader.h +++ b/libc/src/stdio/scanf_core/reader.h @@ -9,20 +9,20 @@ #ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H #define LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H +#include "hdr/types/FILE.h" #include "src/__support/File/file.h" #include "src/__support/macros/attributes.h" // For LIBC_INLINE #include "src/__support/macros/config.h" -#include "hdr/types/FILE.h" #include - namespace LIBC_NAMESPACE_DECL { namespace scanf_core { // We use the name "reader_internal" over "internal" because -// "internal" causes name lookups in files that include the current header to be ambigious -// i.e. `internal::foo` in those files, will try to lookup in `LIBC_NAMESPACE::scanf_core::internal` over `LIBC_NAMESPACE::internal` -// for e.g., `internal::ArgList` in `libc/src/stdio/scanf_core/scanf_main.h` +// "internal" causes name lookups in files that include the current header to be +// ambigious i.e. `internal::foo` in those files, will try to lookup in +// `LIBC_NAMESPACE::scanf_core::internal` over `LIBC_NAMESPACE::internal` for +// e.g., `internal::ArgList` in `libc/src/stdio/scanf_core/scanf_main.h` namespace reader_internal { #if defined(LIBC_TARGET_ARCH_IS_GPU) @@ -68,7 +68,6 @@ LIBC_INLINE void ungetc(int c, void *f) { } // namespace reader_internal - // This is intended to be either a raw string or a buffer syncronized with the // file's internal buffer. struct ReadBuffer { From 76f6a31ca3ef72b53d38358c21718ff6c4208cd6 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 18 Jan 2025 19:56:45 -0500 Subject: [PATCH 15/19] Remove reader.cpp --- libc/src/stdio/scanf_core/CMakeLists.txt | 5 ----- libc/src/stdio/scanf_core/reader.cpp | 22 ---------------------- 2 files changed, 27 deletions(-) delete mode 100644 libc/src/stdio/scanf_core/reader.cpp diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt index 1b61292301814..2bd848e5e7e87 100644 --- a/libc/src/stdio/scanf_core/CMakeLists.txt +++ b/libc/src/stdio/scanf_core/CMakeLists.txt @@ -55,11 +55,8 @@ add_object_library( ) if(LIBC_TARGET_OS_IS_GPU) -# TODO: fix this add_header_library( reader - # SRCS - # reader.cpp HDRS reader.h DEPENDS @@ -70,8 +67,6 @@ add_header_library( elseif( (TARGET libc.src.__support.File.file) OR (NOT LLVM_LIBC_FULL_BUILD) ) add_header_library( reader - # SRCS - # reader.cpp HDRS reader.h DEPENDS diff --git a/libc/src/stdio/scanf_core/reader.cpp b/libc/src/stdio/scanf_core/reader.cpp deleted file mode 100644 index 2c0bc17f6b2aa..0000000000000 --- a/libc/src/stdio/scanf_core/reader.cpp +++ /dev/null @@ -1,22 +0,0 @@ -//===-- Reader definition for scanf -----------------------------*- C++ -*-===// -// -// 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/scanf_core/reader.h" -#include "src/__support/macros/config.h" - -#include - -// TODO: only include one of these depending on build mode -// #include "hdr/types/FILE.h" -// #include "src/__support/File/file.h" - -namespace LIBC_NAMESPACE_DECL { -namespace scanf_core { - -} // namespace scanf_core -} // namespace LIBC_NAMESPACE_DECL From b02a0397ecb7cd5084adc5164a4b9117abcf97b3 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 18 Jan 2025 20:42:08 -0500 Subject: [PATCH 16/19] Possibly redundant dependency for GPU --- libc/src/stdio/scanf_core/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt index 2bd848e5e7e87..7b074d2897bf0 100644 --- a/libc/src/stdio/scanf_core/CMakeLists.txt +++ b/libc/src/stdio/scanf_core/CMakeLists.txt @@ -61,8 +61,6 @@ add_header_library( reader.h DEPENDS libc.src.__support.macros.attributes - libc.src.stdio.getc - libc.src.stdio.ungetc ) elseif( (TARGET libc.src.__support.File.file) OR (NOT LLVM_LIBC_FULL_BUILD) ) add_header_library( From 82ccee6b945459181f1d3a9f54dd64be1e43e613 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Sat, 18 Jan 2025 21:07:14 -0500 Subject: [PATCH 17/19] fix COMPILE_OPTIONS for vfscanf_internal --- libc/src/stdio/scanf_core/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt index 7b074d2897bf0..538dd8a7c0b13 100644 --- a/libc/src/stdio/scanf_core/CMakeLists.txt +++ b/libc/src/stdio/scanf_core/CMakeLists.txt @@ -129,6 +129,7 @@ elseif(TARGET libc.src.__support.File.file OR (NOT LLVM_LIBC_FULL_BUILD)) libc.include.stdio libc.src.__support.File.file libc.src.__support.arg_list + COMPILE_OPTIONS ${use_system_file} ) endif() From 6f14edc144a91b938c7edcf0a4c4a6024ecca308 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Fri, 31 Jan 2025 20:19:10 -0500 Subject: [PATCH 18/19] Add the right guards --- libc/src/stdio/scanf_core/CMakeLists.txt | 4 +--- libc/src/stdio/scanf_core/reader.h | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt index 538dd8a7c0b13..ad195f092d2c2 100644 --- a/libc/src/stdio/scanf_core/CMakeLists.txt +++ b/libc/src/stdio/scanf_core/CMakeLists.txt @@ -71,8 +71,7 @@ add_header_library( libc.src.__support.macros.attributes libc.hdr.types.FILE libc.src.__support.File.file - COMPILE_OPTIONS - ${use_system_file} + ${use_system_file} ) endif() @@ -129,7 +128,6 @@ elseif(TARGET libc.src.__support.File.file OR (NOT LLVM_LIBC_FULL_BUILD)) libc.include.stdio libc.src.__support.File.file libc.src.__support.arg_list - COMPILE_OPTIONS ${use_system_file} ) endif() diff --git a/libc/src/stdio/scanf_core/reader.h b/libc/src/stdio/scanf_core/reader.h index a1a8314182da7..a545a605ff150 100644 --- a/libc/src/stdio/scanf_core/reader.h +++ b/libc/src/stdio/scanf_core/reader.h @@ -10,7 +10,11 @@ #define LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H #include "hdr/types/FILE.h" + +#ifndef LIBC_COPT_STDIO_USE_SYSTEM_FILE #include "src/__support/File/file.h" +#endif + #include "src/__support/macros/attributes.h" // For LIBC_INLINE #include "src/__support/macros/config.h" From 4539ae82c4184171711b5c54dc8f21052374eaed Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh <32487576+vinay-deshmukh@users.noreply.github.com> Date: Wed, 19 Feb 2025 20:16:20 -0500 Subject: [PATCH 19/19] Remove extra spaces --- libc/src/stdio/scanf_core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt index ad195f092d2c2..35b8b3d318a9f 100644 --- a/libc/src/stdio/scanf_core/CMakeLists.txt +++ b/libc/src/stdio/scanf_core/CMakeLists.txt @@ -62,7 +62,7 @@ add_header_library( DEPENDS libc.src.__support.macros.attributes ) -elseif( (TARGET libc.src.__support.File.file) OR (NOT LLVM_LIBC_FULL_BUILD) ) +elseif((TARGET libc.src.__support.File.file) OR (NOT LLVM_LIBC_FULL_BUILD)) add_header_library( reader HDRS