[libc-commits] [libc] 441606f - [libc] Add implementations of fopen, flose, fread, fwrite and fseek.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Wed Mar 23 21:20:40 PDT 2022


Author: Siva Chandra Reddy
Date: 2022-03-24T04:20:12Z
New Revision: 441606f5ff8e4dd884e106a0b6f86f9037c946c4

URL: https://github.com/llvm/llvm-project/commit/441606f5ff8e4dd884e106a0b6f86f9037c946c4
DIFF: https://github.com/llvm/llvm-project/commit/441606f5ff8e4dd884e106a0b6f86f9037c946c4.diff

LOG: [libc] Add implementations of fopen, flose, fread, fwrite and fseek.

A follow up patch will add feof and ferror.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D122327

Added: 
    libc/src/stdio/fclose.cpp
    libc/src/stdio/fclose.h
    libc/src/stdio/fopen.cpp
    libc/src/stdio/fopen.h
    libc/src/stdio/fread.cpp
    libc/src/stdio/fread.h
    libc/src/stdio/fseek.cpp
    libc/src/stdio/fseek.h
    libc/test/src/stdio/fileop_test.cpp
    libc/test/src/stdio/testdata/CMakeLists.txt

Modified: 
    libc/config/linux/x86_64/entrypoints.txt
    libc/spec/stdc.td
    libc/src/stdio/CMakeLists.txt
    libc/src/stdio/fwrite.cpp
    libc/src/stdio/fwrite.h
    libc/test/src/stdio/CMakeLists.txt

Removed: 
    libc/src/stdio/FILE.h
    libc/test/src/stdio/fwrite_test.cpp


################################################################################
diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index e83bddafb984c..5aa64a8dc7dfd 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -229,6 +229,13 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.stdlib.exit
     libc.src.stdlib.getenv
 
+    # stdio.h entrypoints
+    libc.src.stdio.fclose
+    libc.src.stdio.fopen
+    libc.src.stdio.fread
+    libc.src.stdio.fseek
+    libc.src.stdio.fwrite
+
     # signal.h entrypoints
     # TODO: Enable signal.h entrypoints after fixing signal.h
     # libc.src.signal.raise

diff  --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index f7b377d7f70f1..7f57a2ddfab02 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -481,13 +481,39 @@ def StdC : StandardSpec<"stdc"> {
       ],
       [], // Enumerations
       [
+          FunctionSpec<
+              "fclose",
+              RetValSpec<IntType>,
+              [ArgSpec<FILEPtr>]
+          >,
+          FunctionSpec<
+              "fopen",
+              RetValSpec<FILEPtr>,
+              [ArgSpec<ConstCharPtr>,
+               ArgSpec<ConstCharPtr>]
+          >,
+          FunctionSpec<
+              "fread",
+              RetValSpec<SizeTType>,
+              [ArgSpec<VoidRestrictedPtr>,
+               ArgSpec<SizeTType>,
+               ArgSpec<SizeTType>,
+               ArgSpec<FILERestrictedPtr>]
+          >,
+          FunctionSpec<
+              "fseek",
+              RetValSpec<IntType>,
+              [ArgSpec<FILEPtr>,
+               ArgSpec<LongType>,
+               ArgSpec<IntType>]
+          >,
           FunctionSpec<
               "fwrite",
               RetValSpec<SizeTType>,
               [ArgSpec<ConstVoidRestrictedPtr>,
-              ArgSpec<SizeTType>,
-              ArgSpec<SizeTType>,
-              ArgSpec<FILERestrictedPtr>]
+               ArgSpec<SizeTType>,
+               ArgSpec<SizeTType>,
+               ArgSpec<FILERestrictedPtr>]
           >,
       ]
   >;

diff  --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index 337ee22c533dc..2a50f798e3c98 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -1,3 +1,39 @@
+add_entrypoint_object(
+  fopen
+  SRCS
+    fopen.cpp
+  HDRS
+    fopen.h
+  DEPENDS
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+  fclose
+  SRCS
+    fclose.cpp
+  HDRS
+    fclose.h
+  DEPENDS
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+  fread
+  SRCS
+    fread.cpp
+  HDRS
+    fread.h
+  DEPENDS
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
 add_entrypoint_object(
   fwrite
   SRCS
@@ -5,6 +41,19 @@ add_entrypoint_object(
   HDRS
     fwrite.h
   DEPENDS
-    libc.src.threads.mtx_lock
-    libc.src.threads.mtx_unlock
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+  fseek
+  SRCS
+    fseek.cpp
+  HDRS
+    fseek.h
+  DEPENDS
+    libc.include.stdio
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
 )

diff  --git a/libc/src/stdio/fclose.cpp b/libc/src/stdio/fclose.cpp
new file mode 100644
index 0000000000000..48803e33acb3d
--- /dev/null
+++ b/libc/src/stdio/fclose.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of fclose ------------------------------------------===//
+//
+// 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/fclose.h"
+#include "src/__support/File/file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, fclose, (::FILE * stream)) {
+  return reinterpret_cast<__llvm_libc::File *>(stream)->close();
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/stdio/fclose.h b/libc/src/stdio/fclose.h
new file mode 100644
index 0000000000000..21ffa4350391e
--- /dev/null
+++ b/libc/src/stdio/fclose.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of fclose -------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_FCLOSE_H
+#define LLVM_LIBC_SRC_STDIO_FCLOSE_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+int fclose(::FILE *stream);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_FCLOSE_H

diff  --git a/libc/src/stdio/fopen.cpp b/libc/src/stdio/fopen.cpp
new file mode 100644
index 0000000000000..f34b4ed96999a
--- /dev/null
+++ b/libc/src/stdio/fopen.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of fopen -------------------------------------------===//
+//
+// 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/fopen.h"
+#include "src/__support/File/file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(::FILE *, fopen,
+                   (const char *__restrict name, const char *__restrict mode)) {
+  return reinterpret_cast<::FILE *>(__llvm_libc::openfile(name, mode));
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/stdio/fopen.h b/libc/src/stdio/fopen.h
new file mode 100644
index 0000000000000..f8ab0542d2a6f
--- /dev/null
+++ b/libc/src/stdio/fopen.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of fopen --------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_FOPEN_H
+#define LLVM_LIBC_SRC_STDIO_FOPEN_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+::FILE *fopen(const char *__restrict name, const char *__restrict mode);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_FOPEN_H

diff  --git a/libc/src/stdio/fread.cpp b/libc/src/stdio/fread.cpp
new file mode 100644
index 0000000000000..c6a16e24beef6
--- /dev/null
+++ b/libc/src/stdio/fread.cpp
@@ -0,0 +1,23 @@
+//===-- Implementation of fread -------------------------------------------===//
+//
+// 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/fread.h"
+#include "src/__support/File/file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(size_t, fread,
+                   (void *__restrict buffer, size_t size, size_t nmemb,
+                    ::FILE *stream)) {
+  return reinterpret_cast<__llvm_libc::File *>(stream)->read(buffer,
+                                                             size * nmemb);
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/stdio/FILE.h b/libc/src/stdio/fread.h
similarity index 51%
rename from libc/src/stdio/FILE.h
rename to libc/src/stdio/fread.h
index 54bc9b2c87311..995367cda4560 100644
--- a/libc/src/stdio/FILE.h
+++ b/libc/src/stdio/fread.h
@@ -1,4 +1,4 @@
-//===-- Internal definition of FILE -----------------------------*- C++ -*-===//
+//===-- Implementation header of fread --------------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,22 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIBC_SRC_STDIO_FILE_H
-#define LLVM_LIBC_SRC_STDIO_FILE_H
+#ifndef LLVM_LIBC_SRC_STDIO_FREAD_H
+#define LLVM_LIBC_SRC_STDIO_FREAD_H
 
-#include "include/threads.h"
-#include <stddef.h>
+#include <stdio.h>
 
 namespace __llvm_libc {
 
-struct FILE {
-  mtx_t lock;
-
-  using write_function_t = size_t(FILE *, const char *, size_t);
-
-  write_function_t *write;
-};
+size_t fread(void *__restrict buffer, size_t size, size_t nmemb,
+             ::FILE *stream);
 
 } // namespace __llvm_libc
 
-#endif // LLVM_LIBC_SRC_STDIO_FILE_H
+#endif // LLVM_LIBC_SRC_STDIO_FREAD_H

diff  --git a/libc/src/stdio/fseek.cpp b/libc/src/stdio/fseek.cpp
new file mode 100644
index 0000000000000..296acffdd9413
--- /dev/null
+++ b/libc/src/stdio/fseek.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of fseek -------------------------------------------===//
+//
+// 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/fseek.h"
+#include "src/__support/File/file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, fseek, (::FILE * stream, long offset, int whence)) {
+  return reinterpret_cast<__llvm_libc::File *>(stream)->seek(offset, whence);
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/stdio/fseek.h b/libc/src/stdio/fseek.h
new file mode 100644
index 0000000000000..f3865c4efd23f
--- /dev/null
+++ b/libc/src/stdio/fseek.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of fseek --------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_FSEEK_H
+#define LLVM_LIBC_SRC_STDIO_FSEEK_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+int fseek(::FILE *stream, long offset, int whence);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_FSEEK_H

diff  --git a/libc/src/stdio/fwrite.cpp b/libc/src/stdio/fwrite.cpp
index 80cf50ca376e4..0ea0611370dc3 100644
--- a/libc/src/stdio/fwrite.cpp
+++ b/libc/src/stdio/fwrite.cpp
@@ -1,4 +1,4 @@
-//===-- Implementation of fwrite and fwrite_unlocked ------------*- C++ -*-===//
+//===-- Implementation of fwrite ------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,24 +7,17 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/stdio/fwrite.h"
-#include "src/stdio/FILE.h"
-#include "src/threads/mtx_lock.h"
-#include "src/threads/mtx_unlock.h"
+#include "src/__support/File/file.h"
 
-namespace __llvm_libc {
+#include <stdio.h>
 
-size_t fwrite_unlocked(const void *__restrict ptr, size_t size, size_t nmeb,
-                       __llvm_libc::FILE *__restrict stream) {
-  return stream->write(stream, reinterpret_cast<const char *>(ptr),
-                       size * nmeb);
-}
+namespace __llvm_libc {
 
-size_t fwrite(const void *__restrict ptr, size_t size, size_t nmeb,
-              __llvm_libc::FILE *__restrict stream) {
-  __llvm_libc::mtx_lock(&stream->lock);
-  size_t written = fwrite_unlocked(ptr, size, nmeb, stream);
-  __llvm_libc::mtx_unlock(&stream->lock);
-  return written;
+LLVM_LIBC_FUNCTION(size_t, fwrite,
+                   (const void *__restrict buffer, size_t size, size_t nmemb,
+                    ::FILE *stream)) {
+  return reinterpret_cast<__llvm_libc::File *>(stream)->write(buffer,
+                                                              size * nmemb);
 }
 
 } // namespace __llvm_libc

diff  --git a/libc/src/stdio/fwrite.h b/libc/src/stdio/fwrite.h
index 8a71ca105bb08..eb258fcec33b7 100644
--- a/libc/src/stdio/fwrite.h
+++ b/libc/src/stdio/fwrite.h
@@ -9,13 +9,12 @@
 #ifndef LLVM_LIBC_SRC_STDIO_FWRITE_H
 #define LLVM_LIBC_SRC_STDIO_FWRITE_H
 
-#include "src/stdio/FILE.h"
-#include <stddef.h>
+#include <stdio.h>
 
 namespace __llvm_libc {
 
-size_t fwrite(const void *__restrict ptr, size_t size, size_t nmeb,
-              __llvm_libc::FILE *__restrict stream);
+size_t fwrite(const void *__restrict ptr, size_t size, size_t nmemb,
+              ::FILE *__restrict stream);
 
 } // namespace __llvm_libc
 

diff  --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt
index f178eca3c778b..7cb524e2b0800 100644
--- a/libc/test/src/stdio/CMakeLists.txt
+++ b/libc/test/src/stdio/CMakeLists.txt
@@ -1,11 +1,17 @@
 add_libc_testsuite(libc_stdio_unittests)
 
 add_libc_unittest(
-  fwrite_test
+  fileop_test
   SUITE
     libc_stdio_unittests
   SRCS
-    fwrite_test.cpp
+    fileop_test.cpp
   DEPENDS
+    libc.src.stdio.fclose
+    libc.src.stdio.fopen
+    libc.src.stdio.fread
+    libc.src.stdio.fseek
     libc.src.stdio.fwrite
 )
+
+add_subdirectory(testdata)

diff  --git a/libc/test/src/stdio/fileop_test.cpp b/libc/test/src/stdio/fileop_test.cpp
new file mode 100644
index 0000000000000..e515a62a5e768
--- /dev/null
+++ b/libc/test/src/stdio/fileop_test.cpp
@@ -0,0 +1,43 @@
+//===-- Unittests for file operations like fopen, flcose etc --------------===//
+//
+// 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/fclose.h"
+#include "src/stdio/fopen.h"
+#include "src/stdio/fread.h"
+#include "src/stdio/fseek.h"
+#include "src/stdio/fwrite.h"
+#include "utils/UnitTest/Test.h"
+
+#include <stdio.h>
+
+TEST(LlvmLibcStdio, SimpleOperations) {
+  constexpr char FILENAME[] = "testdata/simple_operations.test";
+  ::FILE *file = __llvm_libc::fopen(FILENAME, "w");
+  ASSERT_FALSE(file == nullptr);
+  constexpr char CONTENT[] = "1234567890987654321";
+  ASSERT_EQ(sizeof(CONTENT) - 1,
+            __llvm_libc::fwrite(CONTENT, 1, sizeof(CONTENT) - 1, file));
+  ASSERT_EQ(0, __llvm_libc::fclose(file));
+
+  file = __llvm_libc::fopen(FILENAME, "r");
+  ASSERT_FALSE(file == nullptr);
+
+  constexpr size_t READ_SIZE = 5;
+  char data[READ_SIZE];
+  data[READ_SIZE - 1] = '\0';
+  ASSERT_EQ(__llvm_libc::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1);
+  ASSERT_STREQ(data, "1234");
+  ASSERT_EQ(__llvm_libc::fseek(file, 5, SEEK_CUR), 0);
+  ASSERT_EQ(__llvm_libc::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1);
+  ASSERT_STREQ(data, "0987");
+  ASSERT_EQ(__llvm_libc::fseek(file, -5, SEEK_CUR), 0);
+  ASSERT_EQ(__llvm_libc::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1);
+  ASSERT_STREQ(data, "9098");
+
+  ASSERT_EQ(__llvm_libc::fclose(file), 0);
+}

diff  --git a/libc/test/src/stdio/fwrite_test.cpp b/libc/test/src/stdio/fwrite_test.cpp
deleted file mode 100644
index 9d38d84f160ba..0000000000000
--- a/libc/test/src/stdio/fwrite_test.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//===-- Unittests for fwrite ----------------------------------------------===//
-//
-// 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/CPP/Array.h"
-#include "src/stdio/FILE.h"
-#include "src/stdio/fwrite.h"
-#include "utils/UnitTest/Test.h"
-
-TEST(LlvmLibcStdio, FWriteBasic) {
-  struct StrcpyFile : __llvm_libc::FILE {
-    char *buf;
-  } f;
-  char array[6];
-  f.buf = array;
-  f.write = +[](__llvm_libc::FILE *file, const char *ptr, size_t size) {
-    StrcpyFile *strcpyFile = static_cast<StrcpyFile *>(file);
-    for (size_t i = 0; i < size; ++i)
-      strcpyFile->buf[i] = ptr[i];
-    return size;
-  };
-  EXPECT_EQ(fwrite("hello", 1, 6, &f), 6UL);
-  EXPECT_STREQ(array, "hello");
-}

diff  --git a/libc/test/src/stdio/testdata/CMakeLists.txt b/libc/test/src/stdio/testdata/CMakeLists.txt
new file mode 100644
index 0000000000000..e69de29bb2d1d


        


More information about the libc-commits mailing list