Skip to content

[libc] Migrate from baremetal stdio.h to generic stdio.h #152748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libc/config/baremetal/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ set(TARGET_LIBC_ENTRYPOINTS

# stdio.h entrypoints
libc.src.stdio.asprintf
libc.src.stdio.fopencookie
libc.src.stdio.fprintf
libc.src.stdio.getchar
libc.src.stdio.printf
libc.src.stdio.putchar
Expand Down
2 changes: 2 additions & 0 deletions libc/config/baremetal/arm/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ set(TARGET_LIBC_ENTRYPOINTS

# stdio.h entrypoints
libc.src.stdio.asprintf
libc.src.stdio.fopencookie
libc.src.stdio.fprintf
libc.src.stdio.getchar
libc.src.stdio.printf
libc.src.stdio.putchar
Expand Down
2 changes: 2 additions & 0 deletions libc/config/baremetal/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ set(TARGET_LIBC_ENTRYPOINTS

# stdio.h entrypoints
libc.src.stdio.asprintf
libc.src.stdio.fopencookie
libc.src.stdio.fprintf
libc.src.stdio.getchar
libc.src.stdio.printf
libc.src.stdio.putchar
Expand Down
18 changes: 17 additions & 1 deletion libc/src/__support/File/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ add_object_library(
libc.src.__support.error_or
)

add_header_library(
cookie_file
HDRS
cookie_file.h
DEPENDS
.file
libc.hdr.errno_macros
libc.hdr.types.cookie_io_functions_t
libc.hdr.types.off_t
libc.src.__support.CPP.new
)

add_object_library(
dir
SRCS
Expand All @@ -41,7 +53,11 @@ endif()

add_subdirectory(${LIBC_TARGET_OS})

set(target_file libc.src.__support.File.${LIBC_TARGET_OS}.file)
if(LIBC_TARGET_OS_IS_BAREMETAL)
set(target_file libc.src.__support.File.cookie_file)
else()
set(target_file libc.src.__support.File.${LIBC_TARGET_OS}.file)
endif()
set(target_stdout libc.src.__support.File.${LIBC_TARGET_OS}.stdout)
set(target_stderr libc.src.__support.File.${LIBC_TARGET_OS}.stderr)
set(target_stdin libc.src.__support.File.${LIBC_TARGET_OS}.stdin)
Expand Down
32 changes: 32 additions & 0 deletions libc/src/__support/File/baremetal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
add_object_library(
stdout
SRCS
stdout.cpp
DEPENDS
libc.hdr.stdio_macros
libc.src.__support.File.cookie_file
libc.src.__support.File.file
libc.src.__support.OSUtil.osutil
)

add_object_library(
stdin
SRCS
stdin.cpp
DEPENDS
libc.hdr.stdio_macros
libc.src.__support.File.cookie_file
libc.src.__support.File.file
libc.src.__support.OSUtil.osutil
)

add_object_library(
stderr
SRCS
stderr.cpp
DEPENDS
libc.hdr.stdio_macros
libc.src.__support.File.cookie_file
libc.src.__support.File.file
libc.src.__support.OSUtil.osutil
)
34 changes: 34 additions & 0 deletions libc/src/__support/File/baremetal/stderr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===--- Definition of baremetal stderr -----------------------------------===//
//
// 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 "hdr/stdio_macros.h"
#include "src/__support/File/cookie_file.h"
#include "src/__support/File/file.h"
#include "src/__support/OSUtil/baremetal/io.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

cookie_io_functions_t io_func = {.read = nullptr,
.write = __llvm_libc_stdio_write,
.seek = nullptr,
.close = nullptr};
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
// Buffering is implementation defined. Therefore to save RAM, we use no
// buffering
static CookieFile StdErr(&__llvm_libc_stderr_cookie, io_func, nullptr, 0,
_IONBF, File::mode_flags("w"));
#pragma clang diagnostic pop
File *stderr = &StdErr;

} // namespace LIBC_NAMESPACE_DECL

extern "C" {
FILE *stderr = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::StdErr);
}
34 changes: 34 additions & 0 deletions libc/src/__support/File/baremetal/stdin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===--- Definition of baremetal stdin ------------------------------------===//
//
// 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 "hdr/stdio_macros.h"
#include "src/__support/File/cookie_file.h"
#include "src/__support/File/file.h"
#include "src/__support/OSUtil/baremetal/io.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

cookie_io_functions_t io_func = {.read = __llvm_libc_stdio_read,
.write = nullptr,
.seek = nullptr,
.close = nullptr};
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
// Buffering is implementation defined. Therefore to save RAM, we use no
// buffering
static CookieFile StdIn(&__llvm_libc_stdin_cookie, io_func, nullptr, 0, _IONBF,
File::mode_flags("r"));
#pragma clang diagnostic pop
File *stdin = &StdIn;

} // namespace LIBC_NAMESPACE_DECL

extern "C" {
FILE *stdin = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::StdIn);
}
34 changes: 34 additions & 0 deletions libc/src/__support/File/baremetal/stdout.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===--- Definition of baremetal stdout -----------------------------------===//
//
// 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 "hdr/stdio_macros.h"
#include "src/__support/File/cookie_file.h"
#include "src/__support/File/file.h"
#include "src/__support/OSUtil/baremetal/io.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

cookie_io_functions_t io_func = {.read = nullptr,
.write = __llvm_libc_stdio_write,
.seek = nullptr,
.close = nullptr};
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
// Buffering is implementation defined. Therefore to save RAM, we use no
// buffering
static CookieFile StdOut(&__llvm_libc_stdout_cookie, io_func, nullptr, 0,
_IONBF, File::mode_flags("w"));
#pragma clang diagnostic pop
File *stdout = &StdOut;

} // namespace LIBC_NAMESPACE_DECL

extern "C" {
FILE *stdout = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::StdOut);
}
80 changes: 80 additions & 0 deletions libc/src/__support/File/cookie_file.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//===--- A platform independent cookie file class -------------------------===//
//
// 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 "hdr/errno_macros.h"
#include "hdr/types/cookie_io_functions_t.h"
#include "hdr/types/off_t.h"
#include "src/__support/CPP/new.h"
#include "src/__support/File/file.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

class CookieFile : public LIBC_NAMESPACE::File {
void *cookie;
cookie_io_functions_t ops;

LIBC_INLINE static FileIOResult cookie_write(File *f, const void *data,
size_t size);
LIBC_INLINE static FileIOResult cookie_read(File *f, void *data, size_t size);
LIBC_INLINE static ErrorOr<off_t> cookie_seek(File *f, off_t offset,
int whence);
LIBC_INLINE static int cookie_close(File *f);

public:
LIBC_INLINE CookieFile(void *c, cookie_io_functions_t cops, uint8_t *buffer,
size_t bufsize, int buffer_mode, File::ModeFlags mode)
: File(&cookie_write, &cookie_read, &CookieFile::cookie_seek,
&cookie_close, buffer, bufsize, buffer_mode,
true /* File owns buffer */, mode),
cookie(c), ops(cops) {}
};

LIBC_INLINE FileIOResult CookieFile::cookie_write(File *f, const void *data,
size_t size) {
auto cookie_file = reinterpret_cast<CookieFile *>(f);
if (cookie_file->ops.write == nullptr)
return 0;
return static_cast<size_t>(cookie_file->ops.write(
cookie_file->cookie, reinterpret_cast<const char *>(data), size));
}

LIBC_INLINE FileIOResult CookieFile::cookie_read(File *f, void *data,
size_t size) {
auto cookie_file = reinterpret_cast<CookieFile *>(f);
if (cookie_file->ops.read == nullptr)
return 0;
return static_cast<size_t>(cookie_file->ops.read(
cookie_file->cookie, reinterpret_cast<char *>(data), size));
}

LIBC_INLINE ErrorOr<off_t> CookieFile::cookie_seek(File *f, off_t offset,
int whence) {
auto cookie_file = reinterpret_cast<CookieFile *>(f);
if (cookie_file->ops.seek == nullptr) {
return Error(EINVAL);
}
off64_t offset64 = offset;
int result = cookie_file->ops.seek(cookie_file->cookie, &offset64, whence);
if (result == 0)
return offset64;
return -1;
}

LIBC_INLINE int CookieFile::cookie_close(File *f) {
auto cookie_file = reinterpret_cast<CookieFile *>(f);
if (cookie_file->ops.close == nullptr)
return 0;
int retval = cookie_file->ops.close(cookie_file->cookie);
if (retval != 0)
return retval;
delete cookie_file;
return 0;
}

} // namespace LIBC_NAMESPACE_DECL
39 changes: 0 additions & 39 deletions libc/src/__support/OSUtil/baremetal/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,45 +13,6 @@

namespace LIBC_NAMESPACE_DECL {

// These are intended to be provided by the vendor.
//
// The signature of these types and functions intentionally match `fopencookie`
// which allows the following:
//
// ```
// struct __llvm_libc_stdio_cookie { ... };
// ...
// struct __llvm_libc_stdio_cookie __llvm_libc_stdin_cookie;
// cookie_io_functions_t stdin_func = { .read = __llvm_libc_stdio_read };
// FILE *stdin = fopencookie(&__llvm_libc_stdin_cookie, "r", stdin_func);
// ...
// struct __llvm_libc_stdio_cookie __llvm_libc_stdout_cookie;
// cookie_io_functions_t stdout_func = { .write = __llvm_libc_stdio_write };
// FILE *stdout = fopencookie(&__llvm_libc_stdout_cookie, "w", stdout_func);
// ...
// struct __llvm_libc_stdio_cookie __llvm_libc_stderr_cookie;
// cookie_io_functions_t stderr_func = { .write = __llvm_libc_stdio_write };
// FILE *stderr = fopencookie(&__llvm_libc_stderr_cookie, "w", stderr_func);
// ```
//
// At the same time, implementation of functions like `printf` and `scanf` can
// use `__llvm_libc_stdio_read` and `__llvm_libc_stdio_write` directly to avoid
// the extra indirection.
//
// All three symbols `__llvm_libc_stdin_cookie`, `__llvm_libc_stdout_cookie`,
// and `__llvm_libc_stderr_cookie` must be provided, even if they don't point
// at anything.

struct __llvm_libc_stdio_cookie;

extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stdin_cookie;
extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stdout_cookie;
extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stderr_cookie;

extern "C" ssize_t __llvm_libc_stdio_read(void *cookie, char *buf, size_t size);
extern "C" ssize_t __llvm_libc_stdio_write(void *cookie, const char *buf,
size_t size);

ssize_t read_from_stdin(char *buf, size_t size) {
return __llvm_libc_stdio_read(static_cast<void *>(&__llvm_libc_stdin_cookie),
buf, size);
Expand Down
38 changes: 38 additions & 0 deletions libc/src/__support/OSUtil/baremetal/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,46 @@
#include "src/__support/CPP/string_view.h"
#include "src/__support/macros/config.h"

// These are intended to be provided by the vendor.
//
// The signature of these types and functions intentionally match `fopencookie`
// which allows the following:
//
// ```
// struct __llvm_libc_stdio_cookie { ... };
// ...
// struct __llvm_libc_stdio_cookie __llvm_libc_stdin_cookie;
// cookie_io_functions_t stdin_func = { .read = __llvm_libc_stdio_read };
// FILE *stdin = fopencookie(&__llvm_libc_stdin_cookie, "r", stdin_func);
// ...
// struct __llvm_libc_stdio_cookie __llvm_libc_stdout_cookie;
// cookie_io_functions_t stdout_func = { .write = __llvm_libc_stdio_write };
// FILE *stdout = fopencookie(&__llvm_libc_stdout_cookie, "w", stdout_func);
// ...
// struct __llvm_libc_stdio_cookie __llvm_libc_stderr_cookie;
// cookie_io_functions_t stderr_func = { .write = __llvm_libc_stdio_write };
// FILE *stderr = fopencookie(&__llvm_libc_stderr_cookie, "w", stderr_func);
// ```
//
// At the same time, implementation of functions like `printf` and `scanf` can
// use `__llvm_libc_stdio_read` and `__llvm_libc_stdio_write` directly to avoid
// the extra indirection.
//
// All three symbols `__llvm_libc_stdin_cookie`, `__llvm_libc_stdout_cookie`,
// and `__llvm_libc_stderr_cookie` must be provided, even if they don't point
// at anything.
namespace LIBC_NAMESPACE_DECL {

struct __llvm_libc_stdio_cookie;

extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stdin_cookie;
extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stdout_cookie;
extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stderr_cookie;

extern "C" ssize_t __llvm_libc_stdio_read(void *cookie, char *buf, size_t size);
extern "C" ssize_t __llvm_libc_stdio_write(void *cookie, const char *buf,
size_t size);

ssize_t read_from_stdin(char *buf, size_t size);
void write_to_stderr(cpp::string_view msg);
void write_to_stdout(cpp::string_view msg);
Expand Down
1 change: 1 addition & 0 deletions libc/src/stdio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ add_entrypoint_object(
libc.hdr.types.cookie_io_functions_t
libc.hdr.types.FILE
libc.src.__support.CPP.new
libc.src.__support.File.cookie_file
libc.src.__support.File.file
)

Expand Down
Loading
Loading