[libc-commits] [libc] [libc] Implement more input functions on the GPU (PR #66288)
Joseph Huber via libc-commits
libc-commits at lists.llvm.org
Wed Sep 13 13:37:09 PDT 2023
https://github.com/jhuber6 created https://github.com/llvm/llvm-project/pull/66288:
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.
>From 678bc780481e6e877817e13f7590309b1ca0af35 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 | 4 +
libc/src/stdio/CMakeLists.txt | 98 ++-----------------
libc/src/stdio/generic/CMakeLists.txt | 91 +++++++++++++++++
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 | 77 +++++++++++++++
libc/src/stdio/gpu/fgetc.cpp | 25 +++++
libc/src/stdio/gpu/fgets.cpp | 42 ++++++++
libc/src/stdio/gpu/getc.cpp | 25 +++++
libc/src/stdio/gpu/getchar.cpp | 25 +++++
libc/test/src/stdio/CMakeLists.txt | 4 +-
16 files changed, 298 insertions(+), 93 deletions(-)
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/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..26b944c44e01580 100644
--- a/libc/config/gpu/entrypoints.txt
+++ b/libc/config/gpu/entrypoints.txt
@@ -95,6 +95,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/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index de28b5c02071bf7..0778bb27555f796 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -101,97 +101,6 @@ 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(
fflush
SRCS
@@ -481,6 +390,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..e4047649097f622 100644
--- a/libc/src/stdio/generic/CMakeLists.txt
+++ b/libc/src/stdio/generic/CMakeLists.txt
@@ -140,6 +140,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/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..139ef2e77fe28cc 100644
--- a/libc/src/stdio/gpu/CMakeLists.txt
+++ b/libc/src/stdio/gpu/CMakeLists.txt
@@ -105,6 +105,83 @@ 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
+)
+
add_entrypoint_object(
stdin
SRCS
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..b696d2731b984a5
--- /dev/null
+++ b/libc/src/stdio/gpu/fgets.cpp
@@ -0,0 +1,42 @@
+//===-- 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 <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;
+
+ unsigned char c = '\0';
+ int i;
+ for (i = 0; i < (count - 1) && c != '\n'; ++i) {
+ auto r = file::read(stream, &c, 1);
+ if (r != 1)
+ return nullptr;
+
+ str[i] = c;
+ }
+
+ // If the requested read size makes no sense, an error occured, or no bytes
+ // were read due to an EOF, then return nullptr and don't write the null byte.
+ if (i == 0)
+ 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..c4f0e86aa6f993a 100644
--- a/libc/test/src/stdio/CMakeLists.txt
+++ b/libc/test/src/stdio/CMakeLists.txt
@@ -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
More information about the libc-commits
mailing list