Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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);
}
75 changes: 75 additions & 0 deletions libc/src/__support/File/cookie_file.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//===--- 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;

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

public:
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) {}
};

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));
}

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));
}

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;
}

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