brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.2 KiB · 6df4648 Raw
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