[compiler-rt] b574c52 - [ORC-RT] Add MethodWrapperHandler utility for WrapperFunction.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 19 19:53:28 PDT 2021


Author: Lang Hames
Date: 2021-10-19T18:38:01-07:00
New Revision: b574c52db5335c7e68e5b77dfc40e954fe344d9a

URL: https://github.com/llvm/llvm-project/commit/b574c52db5335c7e68e5b77dfc40e954fe344d9a
DIFF: https://github.com/llvm/llvm-project/commit/b574c52db5335c7e68e5b77dfc40e954fe344d9a.diff

LOG: [ORC-RT] Add MethodWrapperHandler utility for WrapperFunction.

This is an ORC runtime counterpart to a01f772d19d, which introduced the same
functionality into LLVM.

Added: 
    

Modified: 
    compiler-rt/lib/orc/unittests/wrapper_function_utils_test.cpp
    compiler-rt/lib/orc/wrapper_function_utils.h

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/orc/unittests/wrapper_function_utils_test.cpp b/compiler-rt/lib/orc/unittests/wrapper_function_utils_test.cpp
index 12f4a93dceaaa..23d32a041a91d 100644
--- a/compiler-rt/lib/orc/unittests/wrapper_function_utils_test.cpp
+++ b/compiler-rt/lib/orc/unittests/wrapper_function_utils_test.cpp
@@ -103,3 +103,27 @@ TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAddWrapperAndHandle) {
       (void *)&addWrapper, Result, 1, 2));
   EXPECT_EQ(Result, (int32_t)3);
 }
+
+class AddClass {
+public:
+  AddClass(int32_t X) : X(X) {}
+  int32_t addMethod(int32_t Y) { return X + Y; }
+
+private:
+  int32_t X;
+};
+
+static __orc_rt_CWrapperFunctionResult addMethodWrapper(const char *ArgData,
+                                                        size_t ArgSize) {
+  return WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::handle(
+             ArgData, ArgSize, makeMethodWrapperHandler(&AddClass::addMethod))
+      .release();
+}
+
+TEST(WrapperFunctionUtilsTest, WrapperFunctionMethodCallAndHandleRet) {
+  int32_t Result;
+  AddClass AddObj(1);
+  EXPECT_FALSE(!!WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::call(
+      (void *)&addMethodWrapper, Result, ExecutorAddr::fromPtr(&AddObj), 2));
+  EXPECT_EQ(Result, (int32_t)3);
+}

diff  --git a/compiler-rt/lib/orc/wrapper_function_utils.h b/compiler-rt/lib/orc/wrapper_function_utils.h
index cf00d6ec070d4..cf92ad890cd17 100644
--- a/compiler-rt/lib/orc/wrapper_function_utils.h
+++ b/compiler-rt/lib/orc/wrapper_function_utils.h
@@ -16,6 +16,7 @@
 #include "c_api.h"
 #include "common.h"
 #include "error.h"
+#include "executor_address.h"
 #include "simple_packed_serialization.h"
 #include <type_traits>
 
@@ -321,8 +322,8 @@ class WrapperFunction<SPSRetTagT(SPSTagTs...)> {
   static WrapperFunctionResult handle(const char *ArgData, size_t ArgSize,
                                       HandlerT &&Handler) {
     using WFHH =
-        detail::WrapperFunctionHandlerHelper<HandlerT, ResultSerializer,
-                                             SPSTagTs...>;
+        detail::WrapperFunctionHandlerHelper<std::remove_reference_t<HandlerT>,
+                                             ResultSerializer, SPSTagTs...>;
     return WFHH::apply(std::forward<HandlerT>(Handler), ArgData, ArgSize);
   }
 
@@ -354,6 +355,48 @@ class WrapperFunction<void(SPSTagTs...)>
   using WrapperFunction<SPSEmpty(SPSTagTs...)>::handle;
 };
 
+/// A function object that takes an ExecutorAddr as its first argument,
+/// casts that address to a ClassT*, then calls the given method on that
+/// pointer passing in the remaining function arguments. This utility
+/// removes some of the boilerplate from writing wrappers for method calls.
+///
+///   @code{.cpp}
+///   class MyClass {
+///   public:
+///     void myMethod(uint32_t, bool) { ... }
+///   };
+///
+///   // SPS Method signature -- note MyClass object address as first argument.
+///   using SPSMyMethodWrapperSignature =
+///     SPSTuple<SPSExecutorAddr, uint32_t, bool>;
+///
+///   WrapperFunctionResult
+///   myMethodCallWrapper(const char *ArgData, size_t ArgSize) {
+///     return WrapperFunction<SPSMyMethodWrapperSignature>::handle(
+///        ArgData, ArgSize, makeMethodWrapperHandler(&MyClass::myMethod));
+///   }
+///   @endcode
+///
+template <typename RetT, typename ClassT, typename... ArgTs>
+class MethodWrapperHandler {
+public:
+  using MethodT = RetT (ClassT::*)(ArgTs...);
+  MethodWrapperHandler(MethodT M) : M(M) {}
+  RetT operator()(ExecutorAddr ObjAddr, ArgTs &...Args) {
+    return (ObjAddr.toPtr<ClassT *>()->*M)(std::forward<ArgTs>(Args)...);
+  }
+
+private:
+  MethodT M;
+};
+
+/// Create a MethodWrapperHandler object from the given method pointer.
+template <typename RetT, typename ClassT, typename... ArgTs>
+MethodWrapperHandler<RetT, ClassT, ArgTs...>
+makeMethodWrapperHandler(RetT (ClassT::*Method)(ArgTs...)) {
+  return MethodWrapperHandler<RetT, ClassT, ArgTs...>(Method);
+}
+
 } // end namespace __orc_rt
 
 #endif // ORC_RT_WRAPPER_FUNCTION_UTILS_H


        


More information about the llvm-commits mailing list