diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt --- a/libc/config/gpu/entrypoints.txt +++ b/libc/config/gpu/entrypoints.txt @@ -83,9 +83,6 @@ # stdio.h entrypoints libc.src.stdio.puts libc.src.stdio.fputs - libc.src.stdio.fread - libc.src.stdio.fclose - libc.src.stdio.fopen libc.src.stdio.stdin libc.src.stdio.stdout libc.src.stdio.stderr diff --git a/libc/docs/gpu/support.rst b/libc/docs/gpu/support.rst --- a/libc/docs/gpu/support.rst +++ b/libc/docs/gpu/support.rst @@ -124,6 +124,6 @@ ============= ========= ============ puts |check| |check| fputs |check| |check| -fclose |check| |check| -fopen |check| |check| +fclose |check| +fopen |check| ============= ========= ============ diff --git a/libc/src/__support/File/CMakeLists.txt b/libc/src/__support/File/CMakeLists.txt --- a/libc/src/__support/File/CMakeLists.txt +++ b/libc/src/__support/File/CMakeLists.txt @@ -1,4 +1,5 @@ -if(NOT (TARGET libc.src.__support.threads.mutex)) +if(NOT (TARGET libc.src.__support.threads.mutex) + OR LIBC_TARGET_ARCHITECTURE_IS_GPU) # Not all platforms have a mutex implementation. If mutex is unvailable, # we just skip everything about files. return() diff --git a/libc/src/__support/File/file.h b/libc/src/__support/File/file.h --- a/libc/src/__support/File/file.h +++ b/libc/src/__support/File/file.h @@ -38,15 +38,6 @@ public: static constexpr size_t DEFAULT_BUFFER_SIZE = 1024; -// Some platforms like the GPU build cannot support buffering due to extra -// resource usage or hardware constraints. This function allows us to optimize -// out the buffering portions of the code in the general implementation. -#if defined(LIBC_TARGET_ARCH_IS_GPU) - static constexpr bool ENABLE_BUFFER = false; -#else - static constexpr bool ENABLE_BUFFER = true; -#endif - using LockFunc = void(File *); using UnlockFunc = void(File *); @@ -167,8 +158,7 @@ buf(buffer), bufsize(buffer_size), bufmode(buffer_mode), own_buf(owned), mode(modeflags), pos(0), prev_op(FileOp::NONE), read_limit(0), eof(false), err(false) { - if constexpr (ENABLE_BUFFER) - adjust_buf(); + adjust_buf(); } // Buffered write of |len| bytes from |data| without the file lock. diff --git a/libc/src/__support/File/file.cpp b/libc/src/__support/File/file.cpp --- a/libc/src/__support/File/file.cpp +++ b/libc/src/__support/File/file.cpp @@ -25,7 +25,7 @@ prev_op = FileOp::WRITE; - if (!ENABLE_BUFFER || bufmode == _IONBF) { // unbuffered. + if (bufmode == _IONBF) { // unbuffered. size_t ret_val = write_unlocked_nbf(static_cast(data), len); flush_unlocked(); @@ -38,7 +38,7 @@ } FileIOResult File::write_unlocked_nbf(const uint8_t *data, size_t len) { - if (ENABLE_BUFFER && pos > 0) { // If the buffer is not empty + if (pos > 0) { // If the buffer is not empty // Flush the buffer const size_t write_size = pos; auto write_result = platform_write(this, buf, write_size); @@ -325,9 +325,6 @@ } int File::flush_unlocked() { - if constexpr (!ENABLE_BUFFER) - return 0; - if (prev_op == FileOp::WRITE && pos > 0) { auto buf_result = platform_write(this, buf, pos); if (buf_result.has_error() || buf_result.value < pos) { @@ -341,9 +338,6 @@ } int File::set_buffer(void *buffer, size_t size, int buffer_mode) { - if constexpr (!ENABLE_BUFFER) - return EINVAL; - // We do not need to lock the file as this method should be called before // other operations are performed on the file. if (buffer != nullptr && size == 0) diff --git a/libc/src/__support/File/gpu/CMakeLists.txt b/libc/src/__support/File/gpu/CMakeLists.txt deleted file mode 100644 --- a/libc/src/__support/File/gpu/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -add_object_library( - gpu_file - SRCS - file.cpp - DEPENDS - libc.include.stdio - libc.src.errno.errno - libc.src.__support.CPP.new - libc.src.__support.error_or - libc.src.__support.File.file -) - -add_object_library( - gpu_dir - SRCS - dir.cpp - DEPENDS - libc.src.errno.errno - libc.src.__support.error_or - libc.src.__support.File.dir -) diff --git a/libc/src/__support/File/gpu/dir.cpp b/libc/src/__support/File/gpu/dir.cpp deleted file mode 100644 --- a/libc/src/__support/File/gpu/dir.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//===--- GPU implementation of the Dir helpers ----------------------------===// -// -// 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/__support/File/dir.h" - -#include "src/__support/error_or.h" - -namespace __llvm_libc {} // namespace __llvm_libc diff --git a/libc/src/__support/File/gpu/file.cpp b/libc/src/__support/File/gpu/file.cpp deleted file mode 100644 --- a/libc/src/__support/File/gpu/file.cpp +++ /dev/null @@ -1,183 +0,0 @@ -//===--- GPU specialization of the File data structure --------------------===// -// -// 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/__support/File/file.h" - -#include "src/__support/RPC/rpc_client.h" -#include "src/errno/libc_errno.h" // For error macros -#include "src/string/string_utils.h" - -#include - -namespace __llvm_libc { - -namespace { - -FileIOResult write_func(File *, const void *, size_t); -FileIOResult read_func(File *, void *, size_t); -int close_func(File *); - -} // namespace - -class GPUFile : public File { - uintptr_t file; - -public: - constexpr GPUFile(uintptr_t file, File::ModeFlags modeflags) - : File(&write_func, &read_func, nullptr, &close_func, nullptr, 0, _IONBF, - false, modeflags), - file(file) {} - - uintptr_t get_file() const { return file; } -}; - -namespace { - -int write_to_stdout(const void *data, size_t size) { - uint64_t ret = 0; - rpc::Client::Port port = rpc::client.open(); - port.send_n(data, size); - port.recv([&](rpc::Buffer *buffer) { - ret = reinterpret_cast(buffer->data)[0]; - }); - port.close(); - return ret; -} - -int write_to_stderr(const void *data, size_t size) { - uint64_t ret = 0; - rpc::Client::Port port = rpc::client.open(); - port.send_n(data, size); - port.recv([&](rpc::Buffer *buffer) { - ret = reinterpret_cast(buffer->data)[0]; - }); - port.close(); - return ret; -} - -int write_to_stream(uintptr_t file, const void *data, size_t size) { - uint64_t ret = 0; - rpc::Client::Port port = rpc::client.open(); - port.send([&](rpc::Buffer *buffer) { - reinterpret_cast(buffer->data)[0] = file; - }); - port.send_n(data, size); - port.recv([&](rpc::Buffer *buffer) { - ret = reinterpret_cast(buffer->data)[0]; - }); - port.close(); - return ret; -} - -FileIOResult write_func(File *f, const void *data, size_t size) { - auto *gpu_file = reinterpret_cast(f); - int ret = 0; - if (gpu_file == stdout) - ret = write_to_stdout(data, size); - else if (gpu_file == stderr) - ret = write_to_stderr(data, size); - else - ret = write_to_stream(gpu_file->get_file(), data, size); - if (ret < 0) - return {0, -ret}; - return ret; -} - -int read_from_stdin(void *buf, size_t size) { - int ret = 0; - uint64_t recv_size; - rpc::Client::Port port = rpc::client.open(); - port.send([=](rpc::Buffer *buffer) { buffer->data[0] = size; }); - port.recv_n(&buf, &recv_size, [&](uint64_t) { return buf; }); - port.recv([&](rpc::Buffer *buffer) { ret = buffer->data[0]; }); - port.close(); - return ret; -} - -int read_from_stream(uintptr_t file, void *buf, size_t size) { - int ret = 0; - uint64_t recv_size; - // TODO: For large sizes being written to a pointer in global memory, we - // should be able to initiate a H2D memcpy via a separate RPC call at high - // bandwidth. - rpc::Client::Port port = rpc::client.open(); - port.send([=](rpc::Buffer *buffer) { - buffer->data[0] = size; - buffer->data[1] = file; - }); - port.recv_n(&buf, &recv_size, [&](uint64_t) { return buf; }); - port.recv([&](rpc::Buffer *buffer) { ret = buffer->data[0]; }); - port.close(); - return ret; -} - -FileIOResult read_func(File *f, void *buf, size_t size) { - auto *gpu_file = reinterpret_cast(f); - int ret = 0; - if (gpu_file == stdin) - ret = read_from_stdin(buf, size); - else - ret = read_from_stream(gpu_file->get_file(), buf, size); - if (ret < 0) - return {0, -ret}; - return ret; -} - -int close_func(File *file) { - int ret = 0; - GPUFile *gpu_file = reinterpret_cast(file); - rpc::Client::Port port = rpc::client.open(); - port.send_and_recv( - [=](rpc::Buffer *buffer) { buffer->data[0] = gpu_file->get_file(); }, - [&](rpc::Buffer *buffer) { ret = buffer->data[0]; }); - port.close(); - - return ret; -} - -} // namespace - -void *ptr; - -ErrorOr openfile(const char *path, const char *mode) { - auto modeflags = File::mode_flags(mode); - if (modeflags == 0) - return Error(EINVAL); - - uintptr_t file; - rpc::Client::Port port = rpc::client.open(); - port.send_n(path, internal::string_length(path) + 1); - port.send_and_recv( - [=](rpc::Buffer *buffer) { - inline_memcpy(buffer->data, mode, internal::string_length(mode) + 1); - }, - [&](rpc::Buffer *buffer) { file = buffer->data[0]; }); - port.close(); - - static GPUFile gpu_file(0, 0); - gpu_file = GPUFile(file, modeflags); - return &gpu_file; -} - -static GPUFile StdIn(0UL, File::ModeFlags(File::OpenMode::READ)); -File *stdin = &StdIn; - -static GPUFile StdOut(0UL, File::ModeFlags(File::OpenMode::APPEND)); -File *stdout = &StdOut; - -static GPUFile StdErr(0UL, File::ModeFlags(File::OpenMode::APPEND)); -File *stderr = &StdErr; - -} // namespace __llvm_libc - -// Provide the external defintitions of the standard IO streams. -extern "C" { -FILE *stdin = reinterpret_cast(&__llvm_libc::StdIn); -FILE *stderr = reinterpret_cast(&__llvm_libc::StdErr); -FILE *stdout = reinterpret_cast(&__llvm_libc::StdOut); -} diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt --- a/libc/src/stdio/CMakeLists.txt +++ b/libc/src/stdio/CMakeLists.txt @@ -1,3 +1,19 @@ +# Helper function that creates an alias if a target specific implementation +# exists, otherwise it uses a generic one. +function(add_stdio_entrypoint_object entrypoint) + get_fq_target_name("" fq_target_name) + if(TARGET ${fq_target_name}${LIBC_TARGET_OS}.${entrypoint}) + add_entrypoint_object( + ${entrypoint} + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.${entrypoint} + ) + else() + add_entrypoint_object(${entrypoint} ${ARGN}) + endif() +endfunction(add_stdio_entrypoint_object) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) endif() @@ -5,7 +21,7 @@ add_subdirectory(printf_core) add_subdirectory(scanf_core) -add_entrypoint_object( +add_stdio_entrypoint_object( fopen SRCS fopen.cpp @@ -17,7 +33,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fclose SRCS fclose.cpp @@ -30,7 +46,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( clearerr SRCS clearerr.cpp @@ -42,7 +58,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( clearerr_unlocked SRCS clearerr_unlocked.cpp @@ -54,7 +70,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( feof SRCS feof.cpp @@ -66,7 +82,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( feof_unlocked SRCS feof_unlocked.cpp @@ -78,7 +94,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( ferror SRCS ferror.cpp @@ -90,7 +106,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( ferror_unlocked SRCS ferror_unlocked.cpp @@ -102,7 +118,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fgetc SRCS fgetc.cpp @@ -115,7 +131,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fgetc_unlocked SRCS fgetc_unlocked.cpp @@ -128,7 +144,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( getc SRCS getc.cpp @@ -141,7 +157,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( getc_unlocked SRCS getc_unlocked.cpp @@ -154,7 +170,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( getchar SRCS getchar.cpp @@ -167,7 +183,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( getchar_unlocked SRCS getc_unlocked.cpp @@ -180,7 +196,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fgets SRCS fgets.cpp @@ -193,7 +209,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fflush SRCS fflush.cpp @@ -206,7 +222,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( flockfile SRCS flockfile.cpp @@ -218,7 +234,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( funlockfile SRCS funlockfile.cpp @@ -230,7 +246,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fread_unlocked SRCS fread_unlocked.cpp @@ -243,7 +259,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fread SRCS fread.cpp @@ -256,7 +272,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fwrite_unlocked SRCS fwrite_unlocked.cpp @@ -269,7 +285,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fwrite SRCS fwrite.cpp @@ -282,7 +298,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fputc SRCS fputc.cpp @@ -295,7 +311,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( putc SRCS putc.cpp @@ -308,7 +324,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( putchar SRCS putchar.cpp @@ -321,7 +337,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fputs SRCS fputs.cpp @@ -335,7 +351,7 @@ ) -add_entrypoint_object( +add_stdio_entrypoint_object( puts SRCS puts.cpp @@ -348,7 +364,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fseek SRCS fseek.cpp @@ -361,7 +377,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( ungetc SRCS ungetc.cpp @@ -373,7 +389,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( fopencookie SRCS fopencookie.cpp @@ -385,7 +401,7 @@ libc.src.__support.File.file ) -add_entrypoint_object( +add_stdio_entrypoint_object( stdin SRCS stdin.cpp @@ -393,11 +409,9 @@ stdin.h DEPENDS libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( stdout SRCS stdout.cpp @@ -405,11 +419,9 @@ stdout.h DEPENDS libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( stderr SRCS stderr.cpp @@ -417,11 +429,9 @@ stderr.h DEPENDS libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( setbuf SRCS setbuf.cpp @@ -434,7 +444,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( setvbuf SRCS setvbuf.cpp @@ -447,7 +457,7 @@ libc.src.__support.File.platform_file ) -add_entrypoint_object( +add_stdio_entrypoint_object( sscanf SRCS sscanf.cpp @@ -460,7 +470,7 @@ libc.src.stdio.scanf_core.scanf_main ) -add_entrypoint_object( +add_stdio_entrypoint_object( fscanf SRCS fscanf.cpp @@ -471,7 +481,7 @@ libc.src.stdio.scanf_core.vfscanf_internal ) -add_entrypoint_object( +add_stdio_entrypoint_object( scanf SRCS scanf.cpp @@ -482,7 +492,7 @@ libc.src.stdio.scanf_core.vfscanf_internal ) -add_entrypoint_object( +add_stdio_entrypoint_object( sprintf SRCS sprintf.cpp @@ -493,7 +503,7 @@ libc.src.stdio.printf_core.writer ) -add_entrypoint_object( +add_stdio_entrypoint_object( snprintf SRCS snprintf.cpp @@ -517,7 +527,7 @@ set(printf_copts "-DLIBC_COPT_PRINTF_USE_SYSTEM_FILE") endif() -add_entrypoint_object( +add_stdio_entrypoint_object( printf SRCS printf.cpp @@ -529,7 +539,7 @@ ${printf_copts} ) -add_entrypoint_object( +add_stdio_entrypoint_object( fprintf SRCS fprintf.cpp @@ -542,7 +552,7 @@ ${printf_copts} ) -add_entrypoint_object( +add_stdio_entrypoint_object( vsprintf SRCS vsprintf.cpp @@ -553,7 +563,7 @@ libc.src.stdio.printf_core.writer ) -add_entrypoint_object( +add_stdio_entrypoint_object( vsnprintf SRCS vsnprintf.cpp @@ -564,7 +574,7 @@ libc.src.stdio.printf_core.writer ) -add_entrypoint_object( +add_stdio_entrypoint_object( vprintf SRCS vprintf.cpp @@ -576,7 +586,7 @@ ${printf_copts} ) -add_entrypoint_object( +add_stdio_entrypoint_object( vfprintf SRCS vfprintf.cpp @@ -589,7 +599,7 @@ ${printf_copts} ) -add_entrypoint_object( +add_stdio_entrypoint_object( ftell SRCS ftell.cpp diff --git a/libc/src/stdio/gpu/CMakeLists.txt b/libc/src/stdio/gpu/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/src/stdio/gpu/CMakeLists.txt @@ -0,0 +1,31 @@ +add_header_library( + gpu_file + HDRS + file.h + DEPENDS + libc.src.__support.common + libc.src.__support.CPP.string_view + libc.src.__support.RPC.rpc_client +) + +add_entrypoint_object( + puts + SRCS + puts.cpp + HDRS + ../puts.h + DEPENDS + libc.include.stdio + .gpu_file +) + +add_entrypoint_object( + fputs + SRCS + fputs.cpp + HDRS + ../fputs.h + DEPENDS + libc.include.stdio + .gpu_file +) diff --git a/libc/src/stdio/gpu/file.h b/libc/src/stdio/gpu/file.h new file mode 100644 --- /dev/null +++ b/libc/src/stdio/gpu/file.h @@ -0,0 +1,89 @@ +//===--- GPU helper functions--------------------===// +// +// 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/__support/RPC/rpc_client.h" +#include "src/string/string_utils.h" + +#include + +namespace __llvm_libc { +namespace file { + +LIBC_INLINE uint64_t write_to_stdout(const void *data, size_t size) { + uint64_t ret = 0; + rpc::Client::Port port = rpc::client.open(); + port.send_n(data, size); + port.recv([&](rpc::Buffer *buffer) { + ret = reinterpret_cast(buffer->data)[0]; + }); + port.close(); + return ret; +} + +LIBC_INLINE uint64_t write_to_stderr(const void *data, size_t size) { + uint64_t ret = 0; + rpc::Client::Port port = rpc::client.open(); + port.send_n(data, size); + port.recv([&](rpc::Buffer *buffer) { + ret = reinterpret_cast(buffer->data)[0]; + }); + port.close(); + return ret; +} + +LIBC_INLINE uint64_t write_to_stream(uintptr_t file, const void *data, + size_t size) { + uint64_t ret = 0; + rpc::Client::Port port = rpc::client.open(); + port.send([&](rpc::Buffer *buffer) { + reinterpret_cast(buffer->data)[0] = file; + }); + port.send_n(data, size); + port.recv([&](rpc::Buffer *buffer) { + ret = reinterpret_cast(buffer->data)[0]; + }); + port.close(); + return ret; +} + +LIBC_INLINE uint64_t write(FILE *f, const void *data, size_t size) { + if (f == stdout) + return write_to_stdout(data, size); + else if (f == stderr) + return write_to_stderr(data, size); + else + return write_to_stream(reinterpret_cast(f), data, size); +} + +LIBC_INLINE uint64_t read_from_stdin(void *buf, size_t size) { + uint64_t ret = 0; + uint64_t recv_size; + rpc::Client::Port port = rpc::client.open(); + port.send([=](rpc::Buffer *buffer) { buffer->data[0] = size; }); + port.recv_n(&buf, &recv_size, [&](uint64_t) { return buf; }); + port.recv([&](rpc::Buffer *buffer) { ret = buffer->data[0]; }); + port.close(); + return ret; +} + +LIBC_INLINE uint64_t read_from_stream(uintptr_t file, void *buf, size_t size) { + uint64_t ret = 0; + uint64_t recv_size; + rpc::Client::Port port = rpc::client.open(); + port.send([=](rpc::Buffer *buffer) { + buffer->data[0] = size; + buffer->data[1] = file; + }); + port.recv_n(&buf, &recv_size, [&](uint64_t) { return buf; }); + port.recv([&](rpc::Buffer *buffer) { ret = buffer->data[0]; }); + port.close(); + return ret; +} + +} // namespace file +} // namespace __llvm_libc diff --git a/libc/src/stdio/gpu/fputs.cpp b/libc/src/stdio/gpu/fputs.cpp new file mode 100644 --- /dev/null +++ b/libc/src/stdio/gpu/fputs.cpp @@ -0,0 +1,27 @@ +//===-- GPU Implementation of fputs ---------------------------------------===// +// +// 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/fputs.h" +#include "src/__support/CPP/string_view.h" +#include "src/errno/libc_errno.h" +#include "src/stdio/gpu/file.h" + +#include + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, fputs, + (const char *__restrict str, ::FILE *__restrict stream)) { + cpp::string_view str_view(str); + auto written = file::write(stream, str, str_view.size()); + if (written != str_view.size()) + return EOF; + return 0; +} + +} // namespace __llvm_libc diff --git a/libc/src/stdio/gpu/puts.cpp b/libc/src/stdio/gpu/puts.cpp new file mode 100644 --- /dev/null +++ b/libc/src/stdio/gpu/puts.cpp @@ -0,0 +1,29 @@ +//===-- GPU Implementation of puts ----------------------------------------===// +// +// 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/puts.h" +#include "src/__support/CPP/string_view.h" +#include "src/errno/libc_errno.h" +#include "src/stdio/gpu/file.h" + +#include + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, puts, (const char *__restrict str)) { + cpp::string_view str_view(str); + auto written = file::write(stdout, str, str_view.size()); + if (written != str_view.size()) + return EOF; + written = file::write(stdout, "\n", 1); + if (written != 1) + return EOF; + return 0; +} + +} // namespace __llvm_libc diff --git a/libc/src/stdio/stderr.cpp b/libc/src/stdio/stderr.cpp --- a/libc/src/stdio/stderr.cpp +++ b/libc/src/stdio/stderr.cpp @@ -6,8 +6,15 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/File/file.h" +#include "src/__support/macros/attributes.h" #include -extern "C" FILE *stderr; +#ifdef LIBC_TARGET_ARCH_IS_GPU +static struct { +} stub; +namespace __llvm_libc { +FILE *stderr = reinterpret_cast(&stub); +} +extern "C" FILE *stderr = reinterpret_cast(&stub); +#endif diff --git a/libc/src/stdio/stdin.cpp b/libc/src/stdio/stdin.cpp --- a/libc/src/stdio/stdin.cpp +++ b/libc/src/stdio/stdin.cpp @@ -6,8 +6,15 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/File/file.h" +#include "src/__support/macros/attributes.h" #include -extern "C" FILE *stdin; +#ifdef LIBC_TARGET_ARCH_IS_GPU +static struct { +} stub; +namespace __llvm_libc { +FILE *stdin = reinterpret_cast(&stub); +} +extern "C" FILE *stdin = reinterpret_cast(&stub); +#endif diff --git a/libc/src/stdio/stdout.cpp b/libc/src/stdio/stdout.cpp --- a/libc/src/stdio/stdout.cpp +++ b/libc/src/stdio/stdout.cpp @@ -6,8 +6,15 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/File/file.h" +#include "src/__support/macros/attributes.h" #include -extern "C" FILE *stdout; +#ifdef LIBC_TARGET_ARCH_IS_GPU +static struct { +} stub; +namespace __llvm_libc { +FILE *stdout = reinterpret_cast(&stub); +} +extern "C" FILE *stdout = reinterpret_cast(&stub); +#endif diff --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt --- a/libc/test/src/stdio/CMakeLists.txt +++ b/libc/test/src/stdio/CMakeLists.txt @@ -260,6 +260,8 @@ fputs_test.cpp DEPENDS libc.src.stdio.fputs + libc.src.stdio.stdout + libc.src.stdio.stderr ) add_libc_test(