140effc7aSJoseph Huber //===--- GPU helper functions for printf using RPC ------------------------===// 240effc7aSJoseph Huber // 340effc7aSJoseph Huber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 440effc7aSJoseph Huber // See https://llvm.org/LICENSE.txt for license information. 540effc7aSJoseph Huber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 640effc7aSJoseph Huber // 740effc7aSJoseph Huber //===----------------------------------------------------------------------===// 840effc7aSJoseph Huber 9c63112a9Slntue #include "hdr/types/FILE.h" 10197e0125SJoseph Huber #include "src/__support/GPU/utils.h" 1140effc7aSJoseph Huber #include "src/__support/RPC/rpc_client.h" 1240effc7aSJoseph Huber #include "src/__support/arg_list.h" 1303dcefe0SJoseph Huber #include "src/__support/macros/config.h" 1440effc7aSJoseph Huber #include "src/stdio/gpu/file.h" 1540effc7aSJoseph Huber #include "src/string/string_utils.h" 1640effc7aSJoseph Huber 1703dcefe0SJoseph Huber namespace LIBC_NAMESPACE_DECL { 1840effc7aSJoseph Huber 1927d25d1cSJoseph Huber template <uint32_t opcode> 2040effc7aSJoseph Huber LIBC_INLINE int vfprintf_impl(::FILE *__restrict file, 2140effc7aSJoseph Huber const char *__restrict format, size_t format_size, 2240effc7aSJoseph Huber va_list vlist) { 2340effc7aSJoseph Huber uint64_t mask = gpu::get_lane_mask(); 2440effc7aSJoseph Huber rpc::Client::Port port = rpc::client.open<opcode>(); 2540effc7aSJoseph Huber 26*a6ef0debSJoseph Huber if constexpr (opcode == LIBC_PRINTF_TO_STREAM || 27*a6ef0debSJoseph Huber opcode == LIBC_PRINTF_TO_STREAM_PACKED) { 28be0c67c9SJoseph Huber port.send([&](rpc::Buffer *buffer, uint32_t) { 2940effc7aSJoseph Huber buffer->data[0] = reinterpret_cast<uintptr_t>(file); 3040effc7aSJoseph Huber }); 3140effc7aSJoseph Huber } 3240effc7aSJoseph Huber 3340effc7aSJoseph Huber size_t args_size = 0; 3440effc7aSJoseph Huber port.send_n(format, format_size); 35be0c67c9SJoseph Huber port.recv([&](rpc::Buffer *buffer, uint32_t) { 3640effc7aSJoseph Huber args_size = static_cast<size_t>(buffer->data[0]); 3740effc7aSJoseph Huber }); 3840effc7aSJoseph Huber port.send_n(vlist, args_size); 3940effc7aSJoseph Huber 4040effc7aSJoseph Huber uint32_t ret = 0; 4140effc7aSJoseph Huber for (;;) { 4240effc7aSJoseph Huber const char *str = nullptr; 43be0c67c9SJoseph Huber port.recv([&](rpc::Buffer *buffer, uint32_t) { 4440effc7aSJoseph Huber ret = static_cast<uint32_t>(buffer->data[0]); 4540effc7aSJoseph Huber str = reinterpret_cast<const char *>(buffer->data[1]); 4640effc7aSJoseph Huber }); 4740effc7aSJoseph Huber // If any lanes have a string argument it needs to be copied back. 4840effc7aSJoseph Huber if (!gpu::ballot(mask, str)) 4940effc7aSJoseph Huber break; 5040effc7aSJoseph Huber 5140effc7aSJoseph Huber uint64_t size = str ? internal::string_length(str) + 1 : 0; 5240effc7aSJoseph Huber port.send_n(str, size); 5340effc7aSJoseph Huber } 5440effc7aSJoseph Huber 5540effc7aSJoseph Huber port.close(); 5640effc7aSJoseph Huber return ret; 5740effc7aSJoseph Huber } 5840effc7aSJoseph Huber 5940effc7aSJoseph Huber LIBC_INLINE int vfprintf_internal(::FILE *__restrict stream, 6040effc7aSJoseph Huber const char *__restrict format, 6140effc7aSJoseph Huber size_t format_size, va_list vlist) { 6240effc7aSJoseph Huber // The AMDPGU backend uses a packed struct for its varargs. We pass it as a 6340effc7aSJoseph Huber // separate opcode so the server knows how much to advance the pointers. 6440effc7aSJoseph Huber #if defined(LIBC_TARGET_ARCH_IS_AMDGPU) 6540effc7aSJoseph Huber if (stream == stdout) 66*a6ef0debSJoseph Huber return vfprintf_impl<LIBC_PRINTF_TO_STDOUT_PACKED>(stream, format, 6740effc7aSJoseph Huber format_size, vlist); 6840effc7aSJoseph Huber else if (stream == stderr) 69*a6ef0debSJoseph Huber return vfprintf_impl<LIBC_PRINTF_TO_STDERR_PACKED>(stream, format, 7040effc7aSJoseph Huber format_size, vlist); 7140effc7aSJoseph Huber else 72*a6ef0debSJoseph Huber return vfprintf_impl<LIBC_PRINTF_TO_STREAM_PACKED>(stream, format, 7340effc7aSJoseph Huber format_size, vlist); 7440effc7aSJoseph Huber #else 7540effc7aSJoseph Huber if (stream == stdout) 76*a6ef0debSJoseph Huber return vfprintf_impl<LIBC_PRINTF_TO_STDOUT>(stream, format, format_size, 7740effc7aSJoseph Huber vlist); 7840effc7aSJoseph Huber else if (stream == stderr) 79*a6ef0debSJoseph Huber return vfprintf_impl<LIBC_PRINTF_TO_STDERR>(stream, format, format_size, 8040effc7aSJoseph Huber vlist); 8140effc7aSJoseph Huber else 82*a6ef0debSJoseph Huber return vfprintf_impl<LIBC_PRINTF_TO_STREAM>(stream, format, format_size, 8340effc7aSJoseph Huber vlist); 8440effc7aSJoseph Huber #endif 8540effc7aSJoseph Huber } 8640effc7aSJoseph Huber 8703dcefe0SJoseph Huber } // namespace LIBC_NAMESPACE_DECL 88