diff --git a/libc/src/__support/OSUtil/gpu/CMakeLists.txt b/libc/src/__support/OSUtil/gpu/CMakeLists.txt --- a/libc/src/__support/OSUtil/gpu/CMakeLists.txt +++ b/libc/src/__support/OSUtil/gpu/CMakeLists.txt @@ -8,5 +8,7 @@ io.h DEPENDS libc.src.__support.common + libc.src.__support.CPP.string_view libc.src.__support.RPC.rpc_client + libc.src.string.memory_utils.memcpy_implementation ) diff --git a/libc/src/__support/OSUtil/gpu/io.h b/libc/src/__support/OSUtil/gpu/io.h --- a/libc/src/__support/OSUtil/gpu/io.h +++ b/libc/src/__support/OSUtil/gpu/io.h @@ -9,9 +9,11 @@ #ifndef LLVM_LIBC_SRC_SUPPORT_OSUTIL_GPU_IO_H #define LLVM_LIBC_SRC_SUPPORT_OSUTIL_GPU_IO_H +#include "src/__support/CPP/string_view.h" + namespace __llvm_libc { -void write_to_stderr(const char *msg); +void write_to_stderr(cpp::string_view msg); } // namespace __llvm_libc diff --git a/libc/src/__support/OSUtil/gpu/io.cpp b/libc/src/__support/OSUtil/gpu/io.cpp --- a/libc/src/__support/OSUtil/gpu/io.cpp +++ b/libc/src/__support/OSUtil/gpu/io.cpp @@ -8,23 +8,44 @@ #include "io.h" +#include "src/__support/CPP/string_view.h" #include "src/__support/RPC/rpc_client.h" -#include "src/string/string_utils.h" +#include "src/string/memory_utils/memcpy_implementations.h" namespace __llvm_libc { -void write_to_stderr(const char *msg) { - uint64_t length = internal::string_length(msg) + 1; - uint64_t buffer_len = sizeof(rpc::Buffer) - sizeof(uint64_t); - for (uint64_t i = 0; i < length; i += buffer_len) { - rpc::client.run( - [&](rpc::Buffer *buffer) { - buffer->data[0] = rpc::Opcode::PRINT_TO_STDERR; - inline_memcpy(reinterpret_cast(&buffer->data[1]), &msg[i], - (length > buffer_len ? buffer_len : length)); - }, - [](rpc::Buffer *) { /* void */ }); +namespace internal { + +static constexpr size_t BUFFER_SIZE = sizeof(rpc::Buffer) - sizeof(uint64_t); + +LIBC_INLINE bool send_null_terminated(cpp::string_view src) { + bool null_terminated = false; + rpc::client.run( + [&](rpc::Buffer *buffer) { + buffer->data[0] = rpc::Opcode::PRINT_TO_STDERR; + char *data = (char *)&buffer->data[1]; + inline_memcpy(data, src.data(), src.size()); + if (src.size() != BUFFER_SIZE) { + data[src.size()] = '\0'; + null_terminated = true; + } + }, + [](rpc::Buffer *) { /* void */ }); + return null_terminated; +} + +} // namespace internal + +void write_to_stderr(cpp::string_view msg) { + bool send_empty_string = true; + for (; !msg.empty();) { + const auto chunk = msg.substr(0, internal::BUFFER_SIZE); + if (internal::send_null_terminated(chunk)) + send_empty_string = false; + msg.remove_prefix(chunk.size()); } + if (send_empty_string) + internal::send_null_terminated(""); } } // namespace __llvm_libc diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt --- a/libc/src/__support/OSUtil/linux/CMakeLists.txt +++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt @@ -13,4 +13,5 @@ DEPENDS .${LIBC_TARGET_ARCHITECTURE}.linux_${LIBC_TARGET_ARCHITECTURE}_util libc.src.__support.common + libc.src.__support.CPP.string_view ) diff --git a/libc/src/__support/OSUtil/linux/io.h b/libc/src/__support/OSUtil/linux/io.h --- a/libc/src/__support/OSUtil/linux/io.h +++ b/libc/src/__support/OSUtil/linux/io.h @@ -9,16 +9,15 @@ #ifndef LLVM_LIBC_SRC_SUPPORT_OSUTIL_LINUX_IO_H #define LLVM_LIBC_SRC_SUPPORT_OSUTIL_LINUX_IO_H -#include "src/string/string_utils.h" +#include "src/__support/CPP/string_view.h" #include "syscall.h" // For internal syscall function. #include // For syscall numbers. namespace __llvm_libc { -LIBC_INLINE void write_to_stderr(const char *msg) { - __llvm_libc::syscall_impl(SYS_write, 2 /* stderr */, msg, - internal::string_length(msg)); +LIBC_INLINE void write_to_stderr(cpp::string_view msg) { + __llvm_libc::syscall_impl(SYS_write, 2 /* stderr */, msg.data(), msg.size()); } } // namespace __llvm_libc