[libc-commits] [libc] [llvm] [libc] Add RPC helpers for dispatching functions to the host (PR #179085)

Shilei Tian via libc-commits libc-commits at lists.llvm.org
Tue Feb 10 10:57:06 PST 2026


================
@@ -0,0 +1,268 @@
+//===-- Helper functions for client / server dispatch -----------*- C++ -*-===//
+//
+// 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.h"
+#include "rpc_util.h"
+
+namespace rpc {
+namespace {
+
+// Forward declarations needed for the server, we assume these are present.
+extern "C" void *malloc(uint64_t);
+extern "C" void free(const void *);
+
+// Traits to convert between a tuple and binary representation of an argument
+// list.
+template <typename... Ts> struct tuple_bytes {
+  static constexpr uint64_t SIZE = rpc::max(1ul, (0 + ... + sizeof(Ts)));
+  using array_type = rpc::array<uint8_t, SIZE>;
+
+  template <uint64_t... Is>
+  RPC_ATTRS static constexpr array_type pack_impl(rpc::tuple<Ts...> t,
+                                                  rpc::index_sequence<Is...>) {
+    array_type out{};
+    uint8_t *p = out.data();
+    ((rpc::rpc_memcpy(p, &rpc::get<Is>(t), sizeof(Ts)), p += sizeof(Ts)), ...);
+    return out;
+  }
+
+  RPC_ATTRS static constexpr array_type pack(rpc::tuple<Ts...> t) {
+    return pack_impl(t, rpc::index_sequence_for<Ts...>{});
+  }
+
+  template <uint64_t... Is>
+  RPC_ATTRS static constexpr rpc::tuple<Ts...>
+  unpack_impl(const uint8_t *data, rpc::index_sequence<Is...>) {
+    rpc::tuple<Ts...> t{};
+    const uint8_t *p = data;
+    ((rpc::rpc_memcpy(&rpc::get<Is>(t), p, sizeof(Ts)), p += sizeof(Ts)), ...);
+    return t;
+  }
+
+  RPC_ATTRS static constexpr rpc::tuple<Ts...> unpack(const array_type &a) {
+    return unpack_impl(a.data(), rpc::index_sequence_for<Ts...>{});
+  }
+};
+template <typename... Ts>
+struct tuple_bytes<rpc::tuple<Ts...>> : tuple_bytes<Ts...> {};
+
+template <typename> struct function_traits;
+template <typename R, typename... Args> struct function_traits<R (*)(Args...)> {
+  using return_type = R;
+  using arg_types = rpc::tuple<Args...>;
+  static constexpr uint64_t ARITY = sizeof...(Args);
+};
+
+// Client-side dispatch of pointer values. We copy the memory associated with
+// the pointer to the server and recieve back a server-side pointer to replace
+// the client-side pointer in the argument list.
+template <uint64_t Idx, typename Tuple>
+RPC_ATTRS constexpr void prepare_arg(rpc::Client::Port &port, Tuple &t) {
+  using ArgTy = rpc::tuple_element_t<Idx, Tuple>;
+  if constexpr (rpc::is_pointer_v<ArgTy> &&
+                !rpc::is_void_v<rpc::remove_pointer_t<ArgTy>>) {
+    // We assume all constant character arrays are C-strings.
+    uint64_t size{};
+    if constexpr (rpc::is_same_v<ArgTy, const char *>)
+      size = rpc::string_length(rpc::get<Idx>(t));
----------------
shiltian wrote:

Using `string_length` has a drawback that it would return wrong results if there is any 0 in the memory buffer. How do you plan to tackle that?

https://github.com/llvm/llvm-project/pull/179085


More information about the libc-commits mailing list