[libc][NFC] Move aligned access implementations to separate header
[llvm-project.git] / libc / src / __support / File / gpu / file.cpp
blobd474e388b6d9fcfd48cb33ee728a3070b355e380
1 //===--- GPU specialization of the File data structure --------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "src/__support/File/file.h"
11 #include "llvm-libc-types/rpc_opcodes_t.h"
12 #include "src/__support/RPC/rpc_client.h"
13 #include "src/errno/libc_errno.h" // For error macros
14 #include "src/string/string_utils.h"
16 #include <stdio.h>
18 namespace __llvm_libc {
20 namespace {
22 FileIOResult write_func(File *, const void *, size_t);
23 int close_func(File *);
25 } // namespace
27 class GPUFile : public File {
28 uintptr_t file;
30 public:
31 constexpr GPUFile(uintptr_t file, File::ModeFlags modeflags)
32 : File(&write_func, nullptr, nullptr, &close_func, nullptr, 0, _IONBF,
33 false, modeflags),
34 file(file) {}
36 uintptr_t get_file() const { return file; }
39 namespace {
41 int write_to_stdout(const void *data, size_t size) {
42 int ret = 0;
43 rpc::Client::Port port = rpc::client.open<RPC_WRITE_TO_STDOUT>();
44 port.send_n(data, size);
45 port.recv([&](rpc::Buffer *buffer) {
46 ret = reinterpret_cast<int *>(buffer->data)[0];
47 });
48 port.close();
49 return ret;
52 int write_to_stderr(const void *data, size_t size) {
53 int ret = 0;
54 rpc::Client::Port port = rpc::client.open<RPC_WRITE_TO_STDERR>();
55 port.send_n(data, size);
56 port.recv([&](rpc::Buffer *buffer) {
57 ret = reinterpret_cast<int *>(buffer->data)[0];
58 });
59 port.close();
60 return ret;
63 int write_to_stream(uintptr_t file, const void *data, size_t size) {
64 int ret = 0;
65 rpc::Client::Port port = rpc::client.open<RPC_WRITE_TO_STREAM>();
66 port.send([&](rpc::Buffer *buffer) {
67 reinterpret_cast<uintptr_t *>(buffer->data)[0] = file;
68 });
69 port.send_n(data, size);
70 port.recv([&](rpc::Buffer *buffer) {
71 ret = reinterpret_cast<int *>(buffer->data)[0];
72 });
73 port.close();
74 return ret;
77 FileIOResult write_func(File *f, const void *data, size_t size) {
78 auto *gpu_file = reinterpret_cast<GPUFile *>(f);
79 int ret = 0;
80 if (gpu_file == stdout)
81 ret = write_to_stdout(data, size);
82 else if (gpu_file == stderr)
83 ret = write_to_stderr(data, size);
84 else
85 ret = write_to_stream(gpu_file->get_file(), data, size);
86 if (ret < 0)
87 return {0, -ret};
88 return ret;
91 int close_func(File *file) {
92 int ret = 0;
93 GPUFile *gpu_file = reinterpret_cast<GPUFile *>(file);
94 rpc::Client::Port port = rpc::client.open<RPC_CLOSE_FILE>();
95 port.send_and_recv(
96 [=](rpc::Buffer *buffer) { buffer->data[0] = gpu_file->get_file(); },
97 [&](rpc::Buffer *buffer) { ret = buffer->data[0]; });
98 port.close();
100 return ret;
103 } // namespace
105 void *ptr;
107 ErrorOr<File *> openfile(const char *path, const char *mode) {
108 auto modeflags = File::mode_flags(mode);
109 if (modeflags == 0)
110 return Error(EINVAL);
112 uintptr_t file;
113 rpc::Client::Port port = rpc::client.open<RPC_OPEN_FILE>();
114 port.send_n(path, internal::string_length(path) + 1);
115 port.send_and_recv(
116 [=](rpc::Buffer *buffer) {
117 inline_memcpy(buffer->data, mode, internal::string_length(mode) + 1);
119 [&](rpc::Buffer *buffer) { file = buffer->data[0]; });
120 port.close();
122 static GPUFile gpu_file(0, 0);
123 gpu_file = GPUFile(file, modeflags);
124 return &gpu_file;
127 static GPUFile StdIn(0UL, File::ModeFlags(File::OpenMode::READ));
128 File *stdin = &StdIn;
130 static GPUFile StdOut(0UL, File::ModeFlags(File::OpenMode::APPEND));
131 File *stdout = &StdOut;
133 static GPUFile StdErr(0UL, File::ModeFlags(File::OpenMode::APPEND));
134 File *stderr = &StdErr;
136 } // namespace __llvm_libc
138 // Provide the external defintitions of the standard IO streams.
139 extern "C" {
140 FILE *stdin = reinterpret_cast<FILE *>(&__llvm_libc::StdIn);
141 FILE *stderr = reinterpret_cast<FILE *>(&__llvm_libc::StdErr);
142 FILE *stdout = reinterpret_cast<FILE *>(&__llvm_libc::StdOut);