[libc] Add very basic stdio FILE and fwrite

Summary:
This patch adds a very basic `FILE` type and basic `fwrite`.

It also removes `snprintf` from `StdIO`'s function spec because `VarArgType` was causing the generation to fail.

Reviewers: sivachandra, PaulkaToast

Reviewed By: sivachandra

Subscribers: mgorny, MaskRay, tschuett, libc-commits

Differential Revision: https://reviews.llvm.org/D77626
This commit is contained in:
Alex Brachet 2020-04-14 04:02:27 -04:00
parent 54d13b5b2d
commit 99aea57928
12 changed files with 176 additions and 7 deletions

View file

@ -18,6 +18,12 @@ def OffT : TypeDecl<"off_t"> {
}];
}
def FILE : TypeDecl<"FILE"> {
let Decl = [{
typedef struct FILE FILE;
}];
}
def AssertMacro : MacroDef<"assert"> {
let Defn = [{
#undef assert
@ -159,10 +165,11 @@ def StringAPI : PublicAPI<"string.h"> {
def StdIOAPI : PublicAPI<"stdio.h"> {
let TypeDeclarations = [
SizeT,
FILE,
];
let Functions = [
"snprintf",
"fwrite",
];
}

View file

@ -75,6 +75,14 @@ add_gen_header(
../config/${LIBC_TARGET_OS}/signal.h.in
)
add_gen_header(
stdio
DEF_FILE stdio.h.def
GEN_HDR stdio.h
DEPENDS
llvm_libc_common_h
)
add_gen_header(
stdlib
DEF_FILE stdlib.h.def

16
libc/include/stdio.h.def Normal file
View file

@ -0,0 +1,16 @@
//===-- C standard library header stdio.h ---------------------------------===//
//
// 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_STDIO_H
#define LLVM_LIBC_STDIO_H
#include <__llvm-libc-common.h>
%%public_api()
#endif // LLVM_LIBC_STDIO_H

View file

@ -18,6 +18,10 @@ def StdC : StandardSpec<"stdc"> {
NamedType SigHandlerT = NamedType<"__sighandler_t">;
NamedType FILE = NamedType<"FILE">;
PtrType FILEPtr = PtrType<FILE>;
RestrictedPtrType FILERestrictedPtr = RestrictedPtrType<FILE>;
HeaderSpec Assert = HeaderSpec<
"assert.h",
[
@ -190,16 +194,17 @@ def StdC : StandardSpec<"stdc"> {
[], // Macros
[ // Types
SizeTType,
FILE,
],
[], // Enumerations
[
FunctionSpec<
"snprintf",
RetValSpec<IntType>,
[ArgSpec<CharPtr>,
ArgSpec<SizeTType>,
ArgSpec<ConstCharRestrictedPtr>,
ArgSpec<VarArgType>]
"fwrite",
RetValSpec<SizeTType>,
[ArgSpec<ConstVoidRestrictedPtr>,
ArgSpec<SizeTType>,
ArgSpec<SizeTType>,
ArgSpec<FILERestrictedPtr>]
>,
]
>;

View file

@ -2,6 +2,7 @@ add_subdirectory(assert)
add_subdirectory(errno)
add_subdirectory(math)
add_subdirectory(signal)
add_subdirectory(stdio)
add_subdirectory(stdlib)
add_subdirectory(string)
# TODO: Add this target conditional to the target OS.

View file

@ -0,0 +1,10 @@
add_entrypoint_object(
fwrite
SRCS
fwrite.cpp
HDRS
fwrite.h
DEPENDS
libc.src.threads.mtx_lock
libc.src.threads.mtx_unlock
)

27
libc/src/stdio/FILE.h Normal file
View file

@ -0,0 +1,27 @@
//===-- Internal definition of FILE -----------------------------*- 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_FILE_H
#define LLVM_LIBC_SRC_STDIO_FILE_H
#include "include/threads.h"
#include <stddef.h>
namespace __llvm_libc {
struct FILE {
mtx_t lock;
using write_function_t = size_t(FILE *, const char *, size_t);
write_function_t *write;
};
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_STDIO_FILE_H

30
libc/src/stdio/fwrite.cpp Normal file
View file

@ -0,0 +1,30 @@
//===-- Implementation of fwrite and fwrite_unlocked ------------*- 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
//
//===----------------------------------------------------------------------===//
#include "src/stdio/fwrite.h"
#include "src/stdio/FILE.h"
#include "src/threads/mtx_lock.h"
#include "src/threads/mtx_unlock.h"
namespace __llvm_libc {
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);
}
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;
}
} // namespace __llvm_libc

22
libc/src/stdio/fwrite.h Normal file
View file

@ -0,0 +1,22 @@
//===-- Implementation header of fwrite -------------------------*- 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_FWRITE_H
#define LLVM_LIBC_SRC_STDIO_FWRITE_H
#include "src/stdio/FILE.h"
#include <stddef.h>
namespace __llvm_libc {
size_t fwrite(const void *__restrict ptr, size_t size, size_t nmeb,
__llvm_libc::FILE *__restrict stream);
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_STDIO_FWRITE_H

View file

@ -1,6 +1,7 @@
add_subdirectory(assert)
add_subdirectory(errno)
add_subdirectory(signal)
add_subdirectory(stdio)
add_subdirectory(stdlib)
add_subdirectory(string)
add_subdirectory(sys)

View file

@ -0,0 +1,14 @@
add_libc_testsuite(libc_stdio_unittests)
add_libc_unittest(
fwrite_test
SUITE
libc_stdio_unittests
SRCS
fwrite_test.cpp
DEPENDS
libc.src.stdio.fwrite
# TODO(sivachandra): remove private dependencies of fwrite
libc.src.threads.mtx_lock
libc.src.threads.mtx_unlock
)

View file

@ -0,0 +1,28 @@
//===-- 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/stdio/FILE.h"
#include "src/stdio/fwrite.h"
#include "utils/CPP/Array.h"
#include "utils/UnitTest/Test.h"
TEST(Stdio, 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");
}