//===-- GPU implementation of fprintf -------------------------------------===// // // 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 "rpc_fprintf.h" #include "src/__support/CPP/string_view.h" #include "src/__support/GPU/utils.h" #include "src/__support/RPC/rpc_client.h" #include "src/__support/common.h" #include "src/stdio/gpu/file.h" namespace LIBC_NAMESPACE { template int fprintf_impl(::FILE *__restrict file, const char *__restrict format, size_t format_size, void *args, size_t args_size) { uint64_t mask = gpu::get_lane_mask(); rpc::Client::Port port = rpc::client.open(); if constexpr (opcode == RPC_PRINTF_TO_STREAM) { port.send([&](rpc::Buffer *buffer) { buffer->data[0] = reinterpret_cast(file); }); } port.send_n(format, format_size); port.send_n(args, args_size); uint32_t ret = 0; for (;;) { const char *str = nullptr; port.recv([&](rpc::Buffer *buffer) { ret = static_cast(buffer->data[0]); str = reinterpret_cast(buffer->data[1]); }); // If any lanes have a string argument it needs to be copied back. if (!gpu::ballot(mask, str)) break; uint64_t size = str ? internal::string_length(str) + 1 : 0; port.send_n(str, size); } port.close(); return ret; } // TODO: This is a stand-in function that uses a struct pointer and size in // place of varargs. Once varargs support is added we will use that to // implement the real version. LLVM_LIBC_FUNCTION(int, rpc_fprintf, (::FILE *__restrict stream, const char *__restrict format, void *args, size_t size)) { cpp::string_view str(format); if (stream == stdout) return fprintf_impl(stream, format, str.size() + 1, args, size); else if (stream == stderr) return fprintf_impl(stream, format, str.size() + 1, args, size); else return fprintf_impl(stream, format, str.size() + 1, args, size); } } // namespace LIBC_NAMESPACE