1//===-- GPU implementation of fprintf -------------------------------------===//
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//===----------------------------------------------------------------------===//
8
9#include "rpc_fprintf.h"
10
11#include "src/__support/CPP/string_view.h"
12#include "src/__support/GPU/utils.h"
13#include "src/__support/RPC/rpc_client.h"
14#include "src/__support/common.h"
15#include "src/stdio/gpu/file.h"
16
17namespace LIBC_NAMESPACE {
18
19template <uint16_t opcode>
20int fprintf_impl(::FILE *__restrict file, const char *__restrict format,
21 size_t format_size, void *args, size_t args_size) {
22 uint64_t mask = gpu::get_lane_mask();
23 rpc::Client::Port port = rpc::client.open<opcode>();
24
25 if constexpr (opcode == RPC_PRINTF_TO_STREAM) {
26 port.send([&](rpc::Buffer *buffer) {
27 buffer->data[0] = reinterpret_cast<uintptr_t>(file);
28 });
29 }
30
31 port.send_n(src: format, size: format_size);
32 port.send_n(src: args, size: args_size);
33
34 uint32_t ret = 0;
35 for (;;) {
36 const char *str = nullptr;
37 port.recv([&](rpc::Buffer *buffer) {
38 ret = static_cast<uint32_t>(buffer->data[0]);
39 str = reinterpret_cast<const char *>(buffer->data[1]);
40 });
41 // If any lanes have a string argument it needs to be copied back.
42 if (!gpu::ballot(mask, x: str))
43 break;
44
45 uint64_t size = str ? internal::string_length(src: str) + 1 : 0;
46 port.send_n(src: str, size);
47 }
48
49 port.close();
50 return ret;
51}
52
53// TODO: This is a stand-in function that uses a struct pointer and size in
54// place of varargs. Once varargs support is added we will use that to
55// implement the real version.
56LLVM_LIBC_FUNCTION(int, rpc_fprintf,
57 (::FILE *__restrict stream, const char *__restrict format,
58 void *args, size_t size)) {
59 cpp::string_view str(format);
60 if (stream == stdout)
61 return fprintf_impl<RPC_PRINTF_TO_STDOUT>(file: stream, format, format_size: str.size() + 1,
62 args, args_size: size);
63 else if (stream == stderr)
64 return fprintf_impl<RPC_PRINTF_TO_STDERR>(file: stream, format, format_size: str.size() + 1,
65 args, args_size: size);
66 else
67 return fprintf_impl<RPC_PRINTF_TO_STREAM>(file: stream, format, format_size: str.size() + 1,
68 args, args_size: size);
69}
70
71} // namespace LIBC_NAMESPACE
72

source code of libc/src/gpu/rpc_fprintf.cpp