llvm/llvm/include/llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h

//===- WrapperFunctionUtils.h - Utilities for wrapper functions -*- 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
//
//===----------------------------------------------------------------------===//
//
// A buffer for serialized results.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
#define LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H

#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
#include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
#include "llvm/Support/Error.h"

#include <type_traits>

namespace llvm {
namespace orc {
namespace shared {

// Must be kept in-sync with compiler-rt/lib/orc/c-api.h.
CWrapperFunctionResultDataUnion;

// Must be kept in-sync with compiler-rt/lib/orc/c-api.h.
CWrapperFunctionResult;

/// C++ wrapper function result: Same as CWrapperFunctionResult but
/// auto-releases memory.
class WrapperFunctionResult {};

namespace detail {

template <typename SPSArgListT, typename... ArgTs>
WrapperFunctionResult
serializeViaSPSToWrapperFunctionResult(const ArgTs &...Args) {}

template <typename RetT> class WrapperFunctionHandlerCaller {};

template <> class WrapperFunctionHandlerCaller<void> {};

template <typename WrapperFunctionImplT,
          template <typename> class ResultSerializer, typename... SPSTagTs>
class WrapperFunctionHandlerHelper
    : public WrapperFunctionHandlerHelper<
          decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()),
          ResultSerializer, SPSTagTs...> {};

WrapperFunctionHandlerHelper<RetT (ArgTs...), ResultSerializer, SPSTagTs...>;

// Map function pointers to function types.
WrapperFunctionHandlerHelper<RetT (*)(ArgTs...), ResultSerializer, SPSTagTs...>;

// Map non-const member function types to function types.
WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...), ResultSerializer, SPSTagTs...>;

// Map const member function types to function types.
WrapperFunctionHandlerHelper<RetT (ClassT::*)(ArgTs...) const, ResultSerializer, SPSTagTs...>;

template <typename WrapperFunctionImplT,
          template <typename> class ResultSerializer, typename... SPSTagTs>
class WrapperFunctionAsyncHandlerHelper
    : public WrapperFunctionAsyncHandlerHelper<
          decltype(&std::remove_reference_t<WrapperFunctionImplT>::operator()),
          ResultSerializer, SPSTagTs...> {};

WrapperFunctionAsyncHandlerHelper<RetT (SendResultT, ArgTs...), ResultSerializer, SPSTagTs...>;

// Map function pointers to function types.
WrapperFunctionAsyncHandlerHelper<RetT (*)(ArgTs...), ResultSerializer, SPSTagTs...>;

// Map non-const member function types to function types.
WrapperFunctionAsyncHandlerHelper<RetT (ClassT::*)(ArgTs...), ResultSerializer, SPSTagTs...>;

// Map const member function types to function types.
WrapperFunctionAsyncHandlerHelper<RetT (ClassT::*)(ArgTs...) const, ResultSerializer, SPSTagTs...>;

template <typename SPSRetTagT, typename RetT> class ResultSerializer {};

ResultSerializer<SPSRetTagT, Error>;

ResultSerializer<SPSRetTagT, ErrorSuccess>;

ResultSerializer<SPSRetTagT, Expected<T>>;

template <typename SPSRetTagT, typename RetT> class ResultDeserializer {};

template <> class ResultDeserializer<SPSError, Error> {};

ResultDeserializer<SPSExpected<SPSTagT>, Expected<T>>;

template <typename SPSRetTagT, typename RetT> class AsyncCallResultHelper {};

} // end namespace detail

template <typename SPSSignature> class WrapperFunction;

WrapperFunction<SPSRetTagT (SPSTagTs...)>;

WrapperFunction<void (SPSTagTs...)>;

/// 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 {};

/// 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...)) {}

/// Represents a serialized wrapper function call.
/// Serializing calls themselves allows us to batch them: We can make one
/// "run-wrapper-functions" utility and send it a list of calls to run.
///
/// The motivating use-case for this API is JITLink allocation actions, where
/// we want to run multiple functions to finalize linked memory without having
/// to make separate IPC calls for each one.
class WrapperFunctionCall {};

SPSWrapperFunctionCall;

template <>
class SPSSerializationTraits<SPSWrapperFunctionCall, WrapperFunctionCall> {};

} // end namespace shared
} // end namespace orc
} // end namespace llvm

#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H