87 lines · c
1//===--- GPU helper functions for printf using RPC ------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "hdr/types/FILE.h"10#include "src/__support/GPU/utils.h"11#include "src/__support/RPC/rpc_client.h"12#include "src/__support/arg_list.h"13#include "src/stdio/gpu/file.h"14#include "src/string/string_utils.h"15 16namespace LIBC_NAMESPACE_DECL {17 18template <uint32_t opcode>19LIBC_INLINE int vfprintf_impl(::FILE *__restrict file,20 const char *__restrict format, size_t format_size,21 va_list vlist) {22 uint64_t mask = gpu::get_lane_mask();23 rpc::Client::Port port = rpc::client.open<opcode>();24 25 if constexpr (opcode == LIBC_PRINTF_TO_STREAM ||26 opcode == LIBC_PRINTF_TO_STREAM_PACKED) {27 port.send([&](rpc::Buffer *buffer, uint32_t) {28 buffer->data[0] = reinterpret_cast<uintptr_t>(file);29 });30 }31 32 size_t args_size = 0;33 port.send_n(format, format_size);34 port.recv([&](rpc::Buffer *buffer, uint32_t) {35 args_size = static_cast<size_t>(buffer->data[0]);36 });37 port.send_n(vlist, args_size);38 39 uint32_t ret = 0;40 for (;;) {41 const char *str = nullptr;42 port.recv([&](rpc::Buffer *buffer, uint32_t) {43 ret = static_cast<uint32_t>(buffer->data[0]);44 str = reinterpret_cast<const char *>(buffer->data[1]);45 });46 // If any lanes have a string argument it needs to be copied back.47 if (!gpu::ballot(mask, str))48 break;49 50 uint64_t size = str ? internal::string_length(str) + 1 : 0;51 port.send_n(str, size);52 }53 54 port.close();55 return ret;56}57 58LIBC_INLINE int vfprintf_internal(::FILE *__restrict stream,59 const char *__restrict format,60 size_t format_size, va_list vlist) {61 // The AMDPGU backend uses a packed struct for its varargs. We pass it as a62 // separate opcode so the server knows how much to advance the pointers.63#if defined(LIBC_TARGET_ARCH_IS_AMDGPU)64 if (stream == stdout)65 return vfprintf_impl<LIBC_PRINTF_TO_STDOUT_PACKED>(stream, format,66 format_size, vlist);67 else if (stream == stderr)68 return vfprintf_impl<LIBC_PRINTF_TO_STDERR_PACKED>(stream, format,69 format_size, vlist);70 else71 return vfprintf_impl<LIBC_PRINTF_TO_STREAM_PACKED>(stream, format,72 format_size, vlist);73#else74 if (stream == stdout)75 return vfprintf_impl<LIBC_PRINTF_TO_STDOUT>(stream, format, format_size,76 vlist);77 else if (stream == stderr)78 return vfprintf_impl<LIBC_PRINTF_TO_STDERR>(stream, format, format_size,79 vlist);80 else81 return vfprintf_impl<LIBC_PRINTF_TO_STREAM>(stream, format, format_size,82 vlist);83#endif84}85 86} // namespace LIBC_NAMESPACE_DECL87