1 //===--- GPU helper functions for file I/O using RPC ----------------------===//
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/RPC/rpc_client.h"
10 #include "src/__support/macros/config.h"
11 #include "src/string/string_utils.h"
13 #include "hdr/stdio_macros.h" // For stdin/out/err
14 #include "hdr/types/FILE.h"
16 namespace LIBC_NAMESPACE_DECL
{
26 // When copying between the client and server we need to indicate if this is one
27 // of the special streams. We do this by enocding the low order bits of the
28 // pointer to indicate if we need to use the host's standard stream.
29 LIBC_INLINE
uintptr_t from_stream(::FILE *f
) {
31 return reinterpret_cast<uintptr_t>(f
) | Stdin
;
33 return reinterpret_cast<uintptr_t>(f
) | Stdout
;
35 return reinterpret_cast<uintptr_t>(f
) | Stderr
;
36 return reinterpret_cast<uintptr_t>(f
);
39 // Get the associated stream out of an encoded number.
40 LIBC_INLINE ::FILE *to_stream(uintptr_t f
) {
41 ::FILE *stream
= reinterpret_cast<FILE *>(f
& ~0x3ull
);
42 Stream type
= static_cast<Stream
>(f
& 0x3ull
);
52 template <uint32_t opcode
>
53 LIBC_INLINE
uint64_t write_impl(::FILE *file
, const void *data
, size_t size
) {
55 rpc::Client::Port port
= rpc::client
.open
<opcode
>();
57 if constexpr (opcode
== LIBC_WRITE_TO_STREAM
) {
58 port
.send([&](rpc::Buffer
*buffer
, uint32_t) {
59 buffer
->data
[0] = reinterpret_cast<uintptr_t>(file
);
63 port
.send_n(data
, size
);
64 port
.recv([&](rpc::Buffer
*buffer
, uint32_t) {
65 ret
= reinterpret_cast<uint64_t *>(buffer
->data
)[0];
71 LIBC_INLINE
uint64_t write(::FILE *f
, const void *data
, size_t size
) {
73 return write_impl
<LIBC_WRITE_TO_STDOUT
>(f
, data
, size
);
75 return write_impl
<LIBC_WRITE_TO_STDERR
>(f
, data
, size
);
77 return write_impl
<LIBC_WRITE_TO_STREAM
>(f
, data
, size
);
80 LIBC_INLINE
uint64_t read_from_stream(::FILE *file
, void *buf
, size_t size
) {
83 rpc::Client::Port port
= rpc::client
.open
<LIBC_READ_FROM_STREAM
>();
84 port
.send([=](rpc::Buffer
*buffer
, uint32_t) {
85 buffer
->data
[0] = size
;
86 buffer
->data
[1] = from_stream(file
);
88 port
.recv_n(&buf
, &recv_size
, [&](uint64_t) { return buf
; });
89 port
.recv([&](rpc::Buffer
*buffer
, uint32_t) { ret
= buffer
->data
[0]; });
94 LIBC_INLINE
uint64_t read(::FILE *f
, void *data
, size_t size
) {
95 return read_from_stream(f
, data
, size
);
99 } // namespace LIBC_NAMESPACE_DECL