blob: 7b0e60b59baf3f98240dc08798883620afce4ed2 [file] [log] [blame]
//===-- 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 <uint16_t opcode>
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<opcode>();
if constexpr (opcode == RPC_PRINTF_TO_STREAM) {
port.send([&](rpc::Buffer *buffer) {
buffer->data[0] = reinterpret_cast<uintptr_t>(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<uint32_t>(buffer->data[0]);
str = reinterpret_cast<const char *>(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<RPC_PRINTF_TO_STDOUT>(stream, format, str.size() + 1,
args, size);
else if (stream == stderr)
return fprintf_impl<RPC_PRINTF_TO_STDERR>(stream, format, str.size() + 1,
args, size);
else
return fprintf_impl<RPC_PRINTF_TO_STREAM>(stream, format, str.size() + 1,
args, size);
}
} // namespace LIBC_NAMESPACE