[libc-commits] [libc] [libc] Implement more input functions on the GPU (PR #66288)
Joseph Huber via libc-commits
libc-commits at lists.llvm.org
Thu Sep 14 04:33:25 PDT 2023
https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/66288:
>From b85ea4fce0913d468c0609705d21410715e50472 Mon Sep 17 00:00:00 2001
From: Joseph Huber <jhuber6 at vols.utk.edu>
Date: Wed, 13 Sep 2023 15:29:05 -0500
Subject: [PATCH] [libc] Implement more input functions on the GPU
Summary:
This patch implements the `fgets`, `getc`, `fgetc`, and `getchar`
functions on the GPU. Their implementations are straightforward enough.
One thing worth noting is that the implementation of `fgets` will be
extremely slow due to the high latency to read a single char. A faster
solution would be to make a new RPC call to call `fgets` (due to the
special rule that newline or null breaks the stream). But this is left
out because performance isn't the primary concern here.
---
libc/config/gpu/entrypoints.txt | 7 +
libc/include/llvm-libc-types/rpc_opcodes_t.h | 3 +
libc/src/stdio/CMakeLists.txt | 173 +-----------------
libc/src/stdio/generic/CMakeLists.txt | 163 +++++++++++++++++
libc/src/stdio/{ => generic}/clearerr.cpp | 0
.../stdio/{ => generic}/clearerr_unlocked.cpp | 0
libc/src/stdio/{ => generic}/feof.cpp | 0
.../src/stdio/{ => generic}/feof_unlocked.cpp | 0
libc/src/stdio/{ => generic}/ferror.cpp | 0
.../stdio/{ => generic}/ferror_unlocked.cpp | 0
libc/src/stdio/{ => generic}/fgetc.cpp | 0
.../stdio/{ => generic}/fgetc_unlocked.cpp | 0
libc/src/stdio/{ => generic}/fgets.cpp | 0
libc/src/stdio/{ => generic}/getc.cpp | 0
.../src/stdio/{ => generic}/getc_unlocked.cpp | 0
libc/src/stdio/{ => generic}/getchar.cpp | 0
.../stdio/{ => generic}/getchar_unlocked.cpp | 0
libc/src/stdio/gpu/CMakeLists.txt | 113 ++++++++++++
libc/src/stdio/gpu/clearerr.cpp | 28 +++
libc/src/stdio/gpu/feof.cpp | 28 +++
libc/src/stdio/gpu/ferror.cpp | 28 +++
libc/src/stdio/gpu/fgetc.cpp | 25 +++
libc/src/stdio/gpu/fgets.cpp | 46 +++++
libc/src/stdio/gpu/getc.cpp | 25 +++
libc/src/stdio/gpu/getchar.cpp | 25 +++
libc/test/src/stdio/CMakeLists.txt | 6 +-
libc/utils/gpu/server/rpc_server.cpp | 18 ++
27 files changed, 522 insertions(+), 166 deletions(-)
rename libc/src/stdio/{ => generic}/clearerr.cpp (100%)
rename libc/src/stdio/{ => generic}/clearerr_unlocked.cpp (100%)
rename libc/src/stdio/{ => generic}/feof.cpp (100%)
rename libc/src/stdio/{ => generic}/feof_unlocked.cpp (100%)
rename libc/src/stdio/{ => generic}/ferror.cpp (100%)
rename libc/src/stdio/{ => generic}/ferror_unlocked.cpp (100%)
rename libc/src/stdio/{ => generic}/fgetc.cpp (100%)
rename libc/src/stdio/{ => generic}/fgetc_unlocked.cpp (100%)
rename libc/src/stdio/{ => generic}/fgets.cpp (100%)
rename libc/src/stdio/{ => generic}/getc.cpp (100%)
rename libc/src/stdio/{ => generic}/getc_unlocked.cpp (100%)
rename libc/src/stdio/{ => generic}/getchar.cpp (100%)
rename libc/src/stdio/{ => generic}/getchar_unlocked.cpp (100%)
create mode 100644 libc/src/stdio/gpu/clearerr.cpp
create mode 100644 libc/src/stdio/gpu/feof.cpp
create mode 100644 libc/src/stdio/gpu/ferror.cpp
create mode 100644 libc/src/stdio/gpu/fgetc.cpp
create mode 100644 libc/src/stdio/gpu/fgets.cpp
create mode 100644 libc/src/stdio/gpu/getc.cpp
create mode 100644 libc/src/stdio/gpu/getchar.cpp
diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt
index b8d09c9bb8a8bde..ba3e41ce3e5a8ca 100644
--- a/libc/config/gpu/entrypoints.txt
+++ b/libc/config/gpu/entrypoints.txt
@@ -86,6 +86,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.errno.errno
# stdio.h entrypoints
+ libc.src.stdio.feof
+ libc.src.stdio.ferror
+ libc.src.stdio.clearerr
libc.src.stdio.puts
libc.src.stdio.fopen
libc.src.stdio.fclose
@@ -95,6 +98,10 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdio.fputc
libc.src.stdio.putc
libc.src.stdio.putchar
+ libc.src.stdio.fgets
+ libc.src.stdio.fgetc
+ libc.src.stdio.getc
+ libc.src.stdio.getchar
libc.src.stdio.stdin
libc.src.stdio.stdout
libc.src.stdio.stderr
diff --git a/libc/include/llvm-libc-types/rpc_opcodes_t.h b/libc/include/llvm-libc-types/rpc_opcodes_t.h
index 3916c0ad9538922..2c1c89779568a46 100644
--- a/libc/include/llvm-libc-types/rpc_opcodes_t.h
+++ b/libc/include/llvm-libc-types/rpc_opcodes_t.h
@@ -23,6 +23,9 @@ typedef enum : unsigned short {
RPC_FREE = 10,
RPC_HOST_CALL = 11,
RPC_ABORT = 12,
+ RPC_FEOF = 13,
+ RPC_FERROR = 14,
+ RPC_CLEARERR = 15,
} rpc_opcode_t;
#endif // __LLVM_LIBC_TYPES_RPC_OPCODE_H__
diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index de28b5c02071bf7..db1129cfd7e9031 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -29,169 +29,6 @@ endif()
add_subdirectory(printf_core)
add_subdirectory(scanf_core)
-add_entrypoint_object(
- clearerr
- SRCS
- clearerr.cpp
- HDRS
- clearerr.h
- DEPENDS
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- clearerr_unlocked
- SRCS
- clearerr_unlocked.cpp
- HDRS
- clearerr_unlocked.h
- DEPENDS
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- feof
- SRCS
- feof.cpp
- HDRS
- feof.h
- DEPENDS
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- feof_unlocked
- SRCS
- feof_unlocked.cpp
- HDRS
- feof_unlocked.h
- DEPENDS
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- ferror
- SRCS
- ferror.cpp
- HDRS
- ferror.h
- DEPENDS
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- ferror_unlocked
- SRCS
- ferror_unlocked.cpp
- HDRS
- ferror_unlocked.h
- DEPENDS
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- fgetc
- SRCS
- fgetc.cpp
- HDRS
- fgetc.h
- DEPENDS
- libc.src.errno.errno
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- fgetc_unlocked
- SRCS
- fgetc_unlocked.cpp
- HDRS
- fgetc_unlocked.h
- DEPENDS
- libc.src.errno.errno
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- getc
- SRCS
- getc.cpp
- HDRS
- getc.h
- DEPENDS
- libc.src.errno.errno
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- getc_unlocked
- SRCS
- getc_unlocked.cpp
- HDRS
- getc_unlocked.h
- DEPENDS
- libc.src.errno.errno
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- getchar
- SRCS
- getchar.cpp
- HDRS
- getchar.h
- DEPENDS
- libc.src.errno.errno
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- getchar_unlocked
- SRCS
- getc_unlocked.cpp
- HDRS
- getc_unlocked.h
- DEPENDS
- libc.src.errno.errno
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
-add_entrypoint_object(
- fgets
- SRCS
- fgets.cpp
- HDRS
- fgets.h
- DEPENDS
- libc.src.errno.errno
- libc.include.stdio
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
-)
-
add_entrypoint_object(
fflush
SRCS
@@ -470,6 +307,9 @@ add_entrypoint_object(
)
# These entrypoints have multiple potential implementations.
+add_stdio_entrypoint_object(feof)
+add_stdio_entrypoint_object(ferror)
+add_stdio_entrypoint_object(clearerr)
add_stdio_entrypoint_object(fopen)
add_stdio_entrypoint_object(fclose)
add_stdio_entrypoint_object(fread_unlocked)
@@ -481,6 +321,13 @@ add_stdio_entrypoint_object(fwrite)
add_stdio_entrypoint_object(fputc)
add_stdio_entrypoint_object(putc)
add_stdio_entrypoint_object(putchar)
+add_stdio_entrypoint_object(fgetc)
+add_stdio_entrypoint_object(fgetc_unlocked)
+add_stdio_entrypoint_object(getc)
+add_stdio_entrypoint_object(getc_unlocked)
+add_stdio_entrypoint_object(getchar)
+add_stdio_entrypoint_object(getchar_unlocked)
+add_stdio_entrypoint_object(fgets)
add_stdio_entrypoint_object(stdin)
add_stdio_entrypoint_object(stdout)
add_stdio_entrypoint_object(stderr)
diff --git a/libc/src/stdio/generic/CMakeLists.txt b/libc/src/stdio/generic/CMakeLists.txt
index e40e2cc9e04d3e3..b7a9b9b5747e2b4 100644
--- a/libc/src/stdio/generic/CMakeLists.txt
+++ b/libc/src/stdio/generic/CMakeLists.txt
@@ -1,3 +1,75 @@
+add_entrypoint_object(
+ clearerr
+ SRCS
+ clearerr.cpp
+ HDRS
+ ../clearerr.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ clearerr_unlocked
+ SRCS
+ clearerr_unlocked.cpp
+ HDRS
+ ../clearerr_unlocked.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ feof
+ SRCS
+ feof.cpp
+ HDRS
+ ../feof.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ feof_unlocked
+ SRCS
+ feof_unlocked.cpp
+ HDRS
+ ../feof_unlocked.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ ferror
+ SRCS
+ ferror.cpp
+ HDRS
+ ../ferror.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ ferror_unlocked
+ SRCS
+ ferror_unlocked.cpp
+ HDRS
+ ../ferror_unlocked.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
add_entrypoint_object(
fopen
SRCS
@@ -140,6 +212,97 @@ add_entrypoint_object(
libc.src.__support.File.platform_file
)
+add_entrypoint_object(
+ fgetc
+ SRCS
+ fgetc.cpp
+ HDRS
+ ../fgetc.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ fgetc_unlocked
+ SRCS
+ fgetc_unlocked.cpp
+ HDRS
+ ../fgetc_unlocked.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ getc
+ SRCS
+ getc.cpp
+ HDRS
+ ../getc.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ getc_unlocked
+ SRCS
+ getc_unlocked.cpp
+ HDRS
+ ../getc_unlocked.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ getchar
+ SRCS
+ getchar.cpp
+ HDRS
+ ../getchar.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ getchar_unlocked
+ SRCS
+ getc_unlocked.cpp
+ HDRS
+ ../getc_unlocked.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ fgets
+ SRCS
+ fgets.cpp
+ HDRS
+ ../fgets.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
add_entrypoint_object(
stdin
SRCS
diff --git a/libc/src/stdio/clearerr.cpp b/libc/src/stdio/generic/clearerr.cpp
similarity index 100%
rename from libc/src/stdio/clearerr.cpp
rename to libc/src/stdio/generic/clearerr.cpp
diff --git a/libc/src/stdio/clearerr_unlocked.cpp b/libc/src/stdio/generic/clearerr_unlocked.cpp
similarity index 100%
rename from libc/src/stdio/clearerr_unlocked.cpp
rename to libc/src/stdio/generic/clearerr_unlocked.cpp
diff --git a/libc/src/stdio/feof.cpp b/libc/src/stdio/generic/feof.cpp
similarity index 100%
rename from libc/src/stdio/feof.cpp
rename to libc/src/stdio/generic/feof.cpp
diff --git a/libc/src/stdio/feof_unlocked.cpp b/libc/src/stdio/generic/feof_unlocked.cpp
similarity index 100%
rename from libc/src/stdio/feof_unlocked.cpp
rename to libc/src/stdio/generic/feof_unlocked.cpp
diff --git a/libc/src/stdio/ferror.cpp b/libc/src/stdio/generic/ferror.cpp
similarity index 100%
rename from libc/src/stdio/ferror.cpp
rename to libc/src/stdio/generic/ferror.cpp
diff --git a/libc/src/stdio/ferror_unlocked.cpp b/libc/src/stdio/generic/ferror_unlocked.cpp
similarity index 100%
rename from libc/src/stdio/ferror_unlocked.cpp
rename to libc/src/stdio/generic/ferror_unlocked.cpp
diff --git a/libc/src/stdio/fgetc.cpp b/libc/src/stdio/generic/fgetc.cpp
similarity index 100%
rename from libc/src/stdio/fgetc.cpp
rename to libc/src/stdio/generic/fgetc.cpp
diff --git a/libc/src/stdio/fgetc_unlocked.cpp b/libc/src/stdio/generic/fgetc_unlocked.cpp
similarity index 100%
rename from libc/src/stdio/fgetc_unlocked.cpp
rename to libc/src/stdio/generic/fgetc_unlocked.cpp
diff --git a/libc/src/stdio/fgets.cpp b/libc/src/stdio/generic/fgets.cpp
similarity index 100%
rename from libc/src/stdio/fgets.cpp
rename to libc/src/stdio/generic/fgets.cpp
diff --git a/libc/src/stdio/getc.cpp b/libc/src/stdio/generic/getc.cpp
similarity index 100%
rename from libc/src/stdio/getc.cpp
rename to libc/src/stdio/generic/getc.cpp
diff --git a/libc/src/stdio/getc_unlocked.cpp b/libc/src/stdio/generic/getc_unlocked.cpp
similarity index 100%
rename from libc/src/stdio/getc_unlocked.cpp
rename to libc/src/stdio/generic/getc_unlocked.cpp
diff --git a/libc/src/stdio/getchar.cpp b/libc/src/stdio/generic/getchar.cpp
similarity index 100%
rename from libc/src/stdio/getchar.cpp
rename to libc/src/stdio/generic/getchar.cpp
diff --git a/libc/src/stdio/getchar_unlocked.cpp b/libc/src/stdio/generic/getchar_unlocked.cpp
similarity index 100%
rename from libc/src/stdio/getchar_unlocked.cpp
rename to libc/src/stdio/generic/getchar_unlocked.cpp
diff --git a/libc/src/stdio/gpu/CMakeLists.txt b/libc/src/stdio/gpu/CMakeLists.txt
index d35b1925c6a47a0..c47176621144e39 100644
--- a/libc/src/stdio/gpu/CMakeLists.txt
+++ b/libc/src/stdio/gpu/CMakeLists.txt
@@ -3,12 +3,46 @@ add_header_library(
HDRS
file.h
DEPENDS
+ libc.src.__support.RPC.rpc_client
libc.src.__support.common
.stdin
.stdout
.stderr
)
+add_entrypoint_object(
+ feof
+ SRCS
+ feof.cpp
+ HDRS
+ ../feof.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.RPC.rpc_client
+)
+
+add_entrypoint_object(
+ ferror
+ SRCS
+ ferror.cpp
+ HDRS
+ ../ferror.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.RPC.rpc_client
+)
+
+add_entrypoint_object(
+ clearerr
+ SRCS
+ clearerr.cpp
+ HDRS
+ ../clearerr.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.RPC.rpc_client
+)
+
add_entrypoint_object(
fopen
SRCS
@@ -105,6 +139,85 @@ add_entrypoint_object(
.gpu_file
)
+add_entrypoint_object(
+ fgetc
+ SRCS
+ fgetc.cpp
+ HDRS
+ ../fgetc.h
+ DEPENDS
+ libc.include.stdio
+ .gpu_file
+)
+
+add_entrypoint_object(
+ fgetc_unlocked
+ SRCS
+ fgetc_unlocked.cpp
+ HDRS
+ ../fgetc_unlocked.h
+ DEPENDS
+ libc.include.stdio
+ .gpu_file
+)
+
+add_entrypoint_object(
+ getc
+ SRCS
+ getc.cpp
+ HDRS
+ ../getc.h
+ DEPENDS
+ libc.include.stdio
+ .gpu_file
+)
+
+add_entrypoint_object(
+ getc_unlocked
+ SRCS
+ getc_unlocked.cpp
+ HDRS
+ ../getc_unlocked.h
+ DEPENDS
+ libc.include.stdio
+ .gpu_file
+)
+
+add_entrypoint_object(
+ getchar
+ SRCS
+ getchar.cpp
+ HDRS
+ ../getchar.h
+ DEPENDS
+ libc.include.stdio
+ .gpu_file
+)
+
+add_entrypoint_object(
+ getchar_unlocked
+ SRCS
+ getc_unlocked.cpp
+ HDRS
+ ../getc_unlocked.h
+ DEPENDS
+ libc.include.stdio
+ .gpu_file
+)
+
+add_entrypoint_object(
+ fgets
+ SRCS
+ fgets.cpp
+ HDRS
+ ../fgets.h
+ DEPENDS
+ libc.include.stdio
+ .gpu_file
+ .feof
+ .ferror
+)
+
add_entrypoint_object(
stdin
SRCS
diff --git a/libc/src/stdio/gpu/clearerr.cpp b/libc/src/stdio/gpu/clearerr.cpp
new file mode 100644
index 000000000000000..3773a93b46e1795
--- /dev/null
+++ b/libc/src/stdio/gpu/clearerr.cpp
@@ -0,0 +1,28 @@
+//===-- Implementation of clearerr ----------------------------------------===//
+//
+// 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/clearerr.h"
+#include "src/__support/RPC/rpc_client.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(void, clearerr, (::FILE * stream)) {
+ reinterpret_cast<__llvm_libc::File *>(stream)->clearerr();
+ rpc::Client::Port port = rpc::client.open<RPC_FERROR>();
+ port.send_and_recv(
+ [=](rpc::Buffer *buffer) {
+ buffer->data[0] = reinterpret_cast<uintptr_t>(stream);
+ },
+ [&](rpc::Buffer *) {});
+ port.close();
+ return ret;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/gpu/feof.cpp b/libc/src/stdio/gpu/feof.cpp
new file mode 100644
index 000000000000000..8686b283fc39a0f
--- /dev/null
+++ b/libc/src/stdio/gpu/feof.cpp
@@ -0,0 +1,28 @@
+//===-- Implementation of feof --------------------------------------------===//
+//
+// 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/feof.h"
+#include "src/__support/RPC/rpc_client.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, feof, (::FILE * stream)) {
+ int ret;
+ rpc::Client::Port port = rpc::client.open<RPC_FEOF>();
+ port.send_and_recv(
+ [=](rpc::Buffer *buffer) {
+ buffer->data[0] = reinterpret_cast<uintptr_t>(stream);
+ },
+ [&](rpc::Buffer *buffer) { ret = static_cast<int>(buffer->data[0]); });
+ port.close();
+ return ret;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/gpu/ferror.cpp b/libc/src/stdio/gpu/ferror.cpp
new file mode 100644
index 000000000000000..b2a572573d23c1f
--- /dev/null
+++ b/libc/src/stdio/gpu/ferror.cpp
@@ -0,0 +1,28 @@
+//===-- Implementation of ferror ------------------------------------------===//
+//
+// 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/ferror.h"
+#include "src/__support/RPC/rpc_client.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, ferror, (::FILE * stream)) {
+ int ret;
+ rpc::Client::Port port = rpc::client.open<RPC_FERROR>();
+ port.send_and_recv(
+ [=](rpc::Buffer *buffer) {
+ buffer->data[0] = reinterpret_cast<uintptr_t>(stream);
+ },
+ [&](rpc::Buffer *buffer) { ret = static_cast<int>(buffer->data[0]); });
+ port.close();
+ return ret;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/gpu/fgetc.cpp b/libc/src/stdio/gpu/fgetc.cpp
new file mode 100644
index 000000000000000..ff4ef27ccb88e9a
--- /dev/null
+++ b/libc/src/stdio/gpu/fgetc.cpp
@@ -0,0 +1,25 @@
+//===-- GPU implementation of fgetc ---------------------------------------===//
+//
+// 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/fgetc.h"
+#include "file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, fgetc, (::FILE * stream)) {
+ unsigned char c;
+ size_t r = file::read(stream, &c, 1);
+
+ if (r != 1)
+ return EOF;
+ return c;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/gpu/fgets.cpp b/libc/src/stdio/gpu/fgets.cpp
new file mode 100644
index 000000000000000..df00451e2a97034
--- /dev/null
+++ b/libc/src/stdio/gpu/fgets.cpp
@@ -0,0 +1,46 @@
+//===-- GPU implementation of fgets ---------------------------------------===//
+//
+// 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/fgets.h"
+#include "file.h"
+#include "src/stdio/feof.h"
+#include "src/stdio/ferror.h"
+
+#include <stddef.h>
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(char *, fgets,
+ (char *__restrict str, int count,
+ ::FILE *__restrict stream)) {
+ if (count < 1)
+ return nullptr;
+
+ // This implementation is very slow as it makes multiple RPC calls.
+ unsigned char c = '\0';
+ int i = 0;
+ for (; i < count - 1 && c != '\n'; ++i) {
+ auto r = file::read(stream, &c, 1);
+ if (r != 1)
+ break;
+
+ str[i] = c;
+ }
+
+ bool has_error = __llvm_libc::ferror(stream);
+ bool has_eof = __llvm_libc::feof(stream);
+
+ if (has_error || (i == 0 && has_eof))
+ return nullptr;
+
+ str[i] = '\0';
+ return str;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/gpu/getc.cpp b/libc/src/stdio/gpu/getc.cpp
new file mode 100644
index 000000000000000..a2272221d6b7b92
--- /dev/null
+++ b/libc/src/stdio/gpu/getc.cpp
@@ -0,0 +1,25 @@
+//===-- GPU implementation of getc ----------------------------------------===//
+//
+// 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/getc.h"
+#include "file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, getc, (::FILE * stream)) {
+ unsigned char c;
+ size_t r = file::read(stream, &c, 1);
+
+ if (r != 1)
+ return EOF;
+ return c;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/gpu/getchar.cpp b/libc/src/stdio/gpu/getchar.cpp
new file mode 100644
index 000000000000000..a7a6e6c55c13e1a
--- /dev/null
+++ b/libc/src/stdio/gpu/getchar.cpp
@@ -0,0 +1,25 @@
+//===-- GPU implementation of getchar -------------------------------------===//
+//
+// 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/getchar.h"
+#include "file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, getchar, ()) {
+ unsigned char c;
+ size_t r = file::read(stdin, &c, 1);
+
+ if (r != 1)
+ return EOF;
+ return c;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt
index 6090dc1f46c87ef..e042a8bd8be68f2 100644
--- a/libc/test/src/stdio/CMakeLists.txt
+++ b/libc/test/src/stdio/CMakeLists.txt
@@ -298,7 +298,7 @@ add_libc_test(
libc.src.stdio.fopen
)
-add_libc_unittest(
+add_libc_test(
putc_test
SUITE
libc_stdio_unittests
@@ -330,7 +330,7 @@ if(${LIBC_TARGET_OS} STREQUAL "linux")
)
endif()
-add_libc_unittest(
+add_libc_test(
fgetc_test
SUITE
libc_stdio_unittests
@@ -370,7 +370,7 @@ add_libc_unittest(
libc.src.stdio.getc_unlocked
)
-add_libc_unittest(
+add_libc_test(
fgets_test
SUITE
libc_stdio_unittests
diff --git a/libc/utils/gpu/server/rpc_server.cpp b/libc/utils/gpu/server/rpc_server.cpp
index 22e937f0595c6af..70562b7e3e09548 100644
--- a/libc/utils/gpu/server/rpc_server.cpp
+++ b/libc/utils/gpu/server/rpc_server.cpp
@@ -164,6 +164,24 @@ struct Server {
});
break;
}
+ case RPC_FEOF: {
+ port->recv_and_send([](rpc::Buffer *buffer) {
+ buffer->data[0] = feof(reinterpret_cast<FILE *>(buffer->data[0]));
+ });
+ break;
+ }
+ case RPC_FERROR: {
+ port->recv_and_send([](rpc::Buffer *buffer) {
+ buffer->data[0] = ferror(reinterpret_cast<FILE *>(buffer->data[0]));
+ });
+ break;
+ }
+ case RPC_CLEARERR: {
+ port->recv_and_send([](rpc::Buffer *buffer) {
+ clearerr(reinterpret_cast<FILE *>(buffer->data[0]));
+ });
+ break;
+ }
case RPC_NOOP: {
port->recv([](rpc::Buffer *) {});
break;
More information about the libc-commits
mailing list