1 //===--- GPU specialization of the File data structure --------------------===//
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
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"
18 namespace __llvm_libc
{
22 FileIOResult
write_func(File
*, const void *, size_t);
23 int close_func(File
*);
27 class GPUFile
: public File
{
31 constexpr GPUFile(uintptr_t file
, File::ModeFlags modeflags
)
32 : File(&write_func
, nullptr, nullptr, &close_func
, nullptr, 0, _IONBF
,
36 uintptr_t get_file() const { return file
; }
41 int write_to_stdout(const void *data
, size_t size
) {
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];
52 int write_to_stderr(const void *data
, size_t size
) {
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];
63 int write_to_stream(uintptr_t file
, const void *data
, size_t size
) {
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
;
69 port
.send_n(data
, size
);
70 port
.recv([&](rpc::Buffer
*buffer
) {
71 ret
= reinterpret_cast<int *>(buffer
->data
)[0];
77 FileIOResult
write_func(File
*f
, const void *data
, size_t size
) {
78 auto *gpu_file
= reinterpret_cast<GPUFile
*>(f
);
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
);
85 ret
= write_to_stream(gpu_file
->get_file(), data
, size
);
91 int close_func(File
*file
) {
93 GPUFile
*gpu_file
= reinterpret_cast<GPUFile
*>(file
);
94 rpc::Client::Port port
= rpc::client
.open
<RPC_CLOSE_FILE
>();
96 [=](rpc::Buffer
*buffer
) { buffer
->data
[0] = gpu_file
->get_file(); },
97 [&](rpc::Buffer
*buffer
) { ret
= buffer
->data
[0]; });
107 ErrorOr
<File
*> openfile(const char *path
, const char *mode
) {
108 auto modeflags
= File::mode_flags(mode
);
110 return Error(EINVAL
);
113 rpc::Client::Port port
= rpc::client
.open
<RPC_OPEN_FILE
>();
114 port
.send_n(path
, internal::string_length(path
) + 1);
116 [=](rpc::Buffer
*buffer
) {
117 inline_memcpy(buffer
->data
, mode
, internal::string_length(mode
) + 1);
119 [&](rpc::Buffer
*buffer
) { file
= buffer
->data
[0]; });
122 static GPUFile
gpu_file(0, 0);
123 gpu_file
= GPUFile(file
, modeflags
);
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.
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
);