Skip to content

Commit

Permalink
[libc] Add scanf support to the GPU build (#104812)
Browse files Browse the repository at this point in the history
Summary:
The `scanf` function has a "system file" configuration, which is pretty
much what the GPU implementation does at this point. So we should be
able to use it in much the same way.
  • Loading branch information
jhuber6 authored Aug 21, 2024
1 parent b5ba726 commit 6b98a72
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 19 deletions.
2 changes: 2 additions & 0 deletions libc/config/gpu/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdio.vsprintf
libc.src.stdio.asprintf
libc.src.stdio.vasprintf
libc.src.stdio.scanf
libc.src.stdio.fscanf
libc.src.stdio.sscanf
libc.src.stdio.vsscanf
libc.src.stdio.feof
Expand Down
2 changes: 2 additions & 0 deletions libc/docs/gpu/support.rst
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ snprintf |check|
vsprintf |check|
vsnprintf |check|
sscanf |check|
scanf |check|
fscanf |check|
putchar |check| |check|
fclose |check| |check|
fopen |check| |check|
Expand Down
2 changes: 1 addition & 1 deletion libc/src/stdio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ list(APPEND scanf_deps
libc.hdr.types.FILE
)

if(LLVM_LIBC_FULL_BUILD)
if(LLVM_LIBC_FULL_BUILD AND NOT LIBC_TARGET_OS_IS_GPU)
list(APPEND scanf_deps
libc.src.__support.File.file
libc.src.__support.File.platform_file
Expand Down
46 changes: 29 additions & 17 deletions libc/src/stdio/scanf_core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,33 @@ add_object_library(
libc.src.__support.str_to_float
)

if(NOT (TARGET libc.src.__support.File.file) AND LLVM_LIBC_FULL_BUILD)
# Not all platforms have a file implementation. If file is unvailable, and a
# full build is requested, then we must skip all file based printf sections.
return()
if(LIBC_TARGET_OS_IS_GPU)
add_header_library(
vfscanf_internal
HDRS
vfscanf_internal.h
DEPENDS
.reader
.scanf_main
libc.include.stdio
libc.src.__support.arg_list
libc.src.stdio.getc
libc.src.stdio.ungetc
libc.src.stdio.ferror
COMPILE_OPTIONS
-DLIBC_COPT_STDIO_USE_SYSTEM_FILE
)
elseif(TARGET libc.src.__support.File.file OR (NOT LLVM_LIBC_FULL_BUILD))
add_header_library(
vfscanf_internal
HDRS
vfscanf_internal.h
DEPENDS
.reader
.scanf_main
libc.include.stdio
libc.src.__support.File.file
libc.src.__support.arg_list
${use_system_file}
)
endif()

add_header_library(
vfscanf_internal
HDRS
vfscanf_internal.h
DEPENDS
.reader
.scanf_main
libc.include.stdio
libc.src.__support.File.file
libc.src.__support.arg_list
${use_system_file}
)
28 changes: 27 additions & 1 deletion libc/src/stdio/scanf_core/vfscanf_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,43 @@
#include "src/__support/File/file.h"
#include "src/__support/arg_list.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"
#include "src/stdio/scanf_core/reader.h"
#include "src/stdio/scanf_core/scanf_main.h"

#if defined(LIBC_TARGET_ARCH_IS_GPU)
#include "src/stdio/ferror.h"
#include "src/stdio/getc.h"
#include "src/stdio/ungetc.h"
#endif

#include "hdr/types/FILE.h"
#include <stddef.h>

namespace LIBC_NAMESPACE_DECL {

namespace internal {

#ifndef LIBC_COPT_STDIO_USE_SYSTEM_FILE
#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 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)

LIBC_INLINE void flockfile(FILE *f) {
reinterpret_cast<LIBC_NAMESPACE::File *>(f)->lock();
Expand Down

0 comments on commit 6b98a72

Please sign in to comment.