502 lines
17 KiB
C++
502 lines
17 KiB
C++
/*
|
|
* Tencent is pleased to support the open source community by making Puerts available.
|
|
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
|
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may
|
|
* be subject to their corresponding license terms. This file is subject to the terms and conditions defined in file 'LICENSE',
|
|
* which is part of this source code package.
|
|
*/
|
|
|
|
#pragma once
|
|
#include "wasm3.h"
|
|
#include "m3_env.h"
|
|
#include "WasmCommonIncludes.h"
|
|
#include "Wasm3ExportDef.h"
|
|
|
|
typedef uint64_t* wasm_stack_type;
|
|
typedef void* wasm_mem_type;
|
|
|
|
template <typename T>
|
|
struct wasm_remove_const_ref
|
|
{
|
|
using type = typename std::remove_const<typename std::remove_reference<T>::type>::type;
|
|
};
|
|
|
|
template <bool V>
|
|
struct true_false_type
|
|
{
|
|
static constexpr bool value = V;
|
|
};
|
|
|
|
template <typename T, typename Enable = void>
|
|
struct _wasm_is_simple_type;
|
|
|
|
//定义简单的类型,该类型会直接被放在栈上
|
|
template <>
|
|
struct _wasm_is_simple_type<bool> : true_false_type<true>
|
|
{
|
|
};
|
|
// template<> struct _wasm_is_simple_type<char> : true_false_type<true> {};
|
|
// template<> struct _wasm_is_simple_type<unsigned char> : true_false_type<true> {};
|
|
template <>
|
|
struct _wasm_is_simple_type<int32> : true_false_type<true>
|
|
{
|
|
};
|
|
template <>
|
|
struct _wasm_is_simple_type<uint32> : true_false_type<true>
|
|
{
|
|
};
|
|
template <>
|
|
struct _wasm_is_simple_type<int64> : true_false_type<true>
|
|
{
|
|
};
|
|
template <>
|
|
struct _wasm_is_simple_type<uint64> : true_false_type<true>
|
|
{
|
|
};
|
|
template <>
|
|
struct _wasm_is_simple_type<float> : true_false_type<true>
|
|
{
|
|
};
|
|
template <>
|
|
struct _wasm_is_simple_type<double> : true_false_type<true>
|
|
{
|
|
};
|
|
// enum为true,非enum为false
|
|
template <typename T>
|
|
struct _wasm_is_simple_type<T, typename std::enable_if<std::is_enum<T>::value>::type> : true_false_type<true>
|
|
{
|
|
};
|
|
template <typename T>
|
|
struct _wasm_is_simple_type<T, typename std::enable_if<!std::is_enum<T>::value>::type> : true_false_type<false>
|
|
{
|
|
};
|
|
|
|
template <typename T>
|
|
struct wasm_is_simple_type
|
|
{
|
|
static constexpr bool value = _wasm_is_simple_type<typename wasm_remove_const_ref<T>::type>::value;
|
|
};
|
|
|
|
static_assert(wasm_is_simple_type<const int&>::value, "");
|
|
static_assert(wasm_is_simple_type<int&>::value, "");
|
|
static_assert(wasm_is_simple_type<int>::value, "");
|
|
static_assert(wasm_is_simple_type<const int>::value, "");
|
|
static_assert(!wasm_is_simple_type<void*>::value, "");
|
|
|
|
//定义复杂类型,该类型会被当作指针放在栈上
|
|
template <typename T>
|
|
struct _wasm_is_complex_type
|
|
{
|
|
//这里有点奇怪
|
|
// 属性数量大于1的结构体当指针
|
|
// 小于32的结构体当int32,小于64的结构体当int64,大于64的当指针
|
|
// 我们判断不了属性数量,所以强制规定,结构体必须大于64
|
|
static constexpr bool value =
|
|
!wasm_is_simple_type<T>::value && std::is_class<T>::value && std::is_trivially_copyable<T>::value && (sizeof(T) > 8);
|
|
};
|
|
|
|
template <typename T>
|
|
struct wasm_is_complex_type
|
|
{
|
|
static constexpr bool value = _wasm_is_complex_type<typename wasm_remove_const_ref<T>::type>::value;
|
|
};
|
|
template <>
|
|
struct wasm_is_complex_type<void>
|
|
{
|
|
static constexpr bool value = false;
|
|
};
|
|
|
|
static_assert(!wasm_is_complex_type<void*>::value, "");
|
|
|
|
template <typename T>
|
|
struct wasm_is_support_pointer_type
|
|
{
|
|
using No_PTr = typename std::remove_pointer<T>::type;
|
|
static constexpr bool value =
|
|
std::is_pointer<T>::value && !wasm_is_complex_type<No_PTr>::value && !wasm_is_simple_type<No_PTr>::value;
|
|
};
|
|
|
|
template <typename... Args>
|
|
struct wasm_is_all_support_type;
|
|
|
|
template <typename T>
|
|
struct wasm_is_all_support_type<T>
|
|
{
|
|
static constexpr bool value =
|
|
wasm_is_complex_type<T>::value || wasm_is_simple_type<T>::value || wasm_is_support_pointer_type<T>::value;
|
|
};
|
|
|
|
template <typename T, typename... Args>
|
|
struct wasm_is_all_support_type<T, Args...>
|
|
{
|
|
static constexpr bool value = wasm_is_all_support_type<T>::value && wasm_is_all_support_type<Args...>::value;
|
|
};
|
|
|
|
template <typename T, typename Enabled = void>
|
|
struct _wasm_call_params_translator
|
|
{
|
|
};
|
|
|
|
template <>
|
|
struct _wasm_call_params_translator<float>
|
|
{
|
|
using type = float;
|
|
};
|
|
|
|
template <>
|
|
struct _wasm_call_params_translator<double>
|
|
{
|
|
using type = double;
|
|
};
|
|
|
|
template <typename T>
|
|
struct _wasm_call_params_translator<T, typename std::enable_if<wasm_is_simple_type<T>::value && (sizeof(T) <= 4)>::type>
|
|
{
|
|
using type = int32;
|
|
};
|
|
|
|
template <typename T>
|
|
struct _wasm_call_params_translator<T,
|
|
typename std::enable_if<wasm_is_simple_type<T>::value && (sizeof(T) > 4) && (sizeof(T) <= 8)>::type>
|
|
{
|
|
using type = int64;
|
|
};
|
|
|
|
template <typename T>
|
|
struct _wasm_call_params_translator<T, typename std::enable_if<wasm_is_complex_type<T>::value>::type>
|
|
{
|
|
using type = WASM_PTR;
|
|
};
|
|
|
|
template <typename T>
|
|
struct _wasm_call_params_translator<T, typename std::enable_if<wasm_is_support_pointer_type<T>::value>::type>
|
|
{
|
|
using type = WASM_PTR;
|
|
};
|
|
|
|
template <typename T>
|
|
struct wasm_call_params_translator
|
|
{
|
|
using translated_type = typename _wasm_call_params_translator<typename wasm_remove_const_ref<T>::type>::type;
|
|
};
|
|
|
|
template <typename T, typename U>
|
|
using is_enum_of_t = typename std::enable_if<std::is_enum<T>::value && std::is_same<std::underlying_type_t<T>, U>::value>::type;
|
|
|
|
template <char c>
|
|
struct m3_sig
|
|
{
|
|
static const char value = c;
|
|
};
|
|
template <typename T, typename = void>
|
|
struct _m3_type_to_sig;
|
|
|
|
template <typename T>
|
|
struct _m3_type_to_sig<T, is_enum_of_t<T, int32_t>> : m3_sig<'i'>
|
|
{
|
|
};
|
|
|
|
template <class T>
|
|
struct _m3_type_to_sig<T, is_enum_of_t<T, int64_t>> : m3_sig<'I'>
|
|
{
|
|
};
|
|
|
|
template <>
|
|
struct _m3_type_to_sig<bool> : m3_sig<'i'>
|
|
{
|
|
};
|
|
template <>
|
|
struct _m3_type_to_sig<char> : m3_sig<'i'>
|
|
{
|
|
};
|
|
template <>
|
|
struct _m3_type_to_sig<unsigned char> : m3_sig<'i'>
|
|
{
|
|
};
|
|
template <>
|
|
struct _m3_type_to_sig<int32_t> : m3_sig<'i'>
|
|
{
|
|
};
|
|
template <>
|
|
struct _m3_type_to_sig<uint32_t> : m3_sig<'i'>
|
|
{
|
|
};
|
|
template <>
|
|
struct _m3_type_to_sig<int64_t> : m3_sig<'I'>
|
|
{
|
|
};
|
|
template <>
|
|
struct _m3_type_to_sig<uint64_t> : m3_sig<'I'>
|
|
{
|
|
};
|
|
template <>
|
|
struct _m3_type_to_sig<float> : m3_sig<'f'>
|
|
{
|
|
};
|
|
template <>
|
|
struct _m3_type_to_sig<double> : m3_sig<'F'>
|
|
{
|
|
};
|
|
template <>
|
|
struct _m3_type_to_sig<void> : m3_sig<'v'>
|
|
{
|
|
};
|
|
template <typename T>
|
|
struct _m3_type_to_sig<T, typename std::is_reference<T>::type> : m3_sig<'*'>
|
|
{
|
|
};
|
|
template <typename T>
|
|
struct _m3_type_to_sig<T, typename std::enable_if<wasm_is_complex_type<T>::value>::type> : m3_sig<'*'>
|
|
{
|
|
};
|
|
template <typename T>
|
|
struct _m3_type_to_sig<T, typename std::enable_if<wasm_is_support_pointer_type<T>::value>::type> : m3_sig<'*'>
|
|
{
|
|
};
|
|
|
|
template <typename T, typename Enable = void>
|
|
struct m3_type_to_sig;
|
|
|
|
//引用当指针处理
|
|
template <typename T>
|
|
struct m3_type_to_sig<T, typename std::enable_if<std::is_reference<T>::value>::type>
|
|
{
|
|
using TT = typename wasm_remove_const_ref<T>::type;
|
|
static const char value = '*';
|
|
};
|
|
|
|
template <typename T>
|
|
struct m3_type_to_sig<T, typename std::enable_if<!std::is_reference<T>::value>::type>
|
|
{
|
|
using TT = typename wasm_remove_const_ref<T>::type;
|
|
static const char value = _m3_type_to_sig<TT>::value;
|
|
};
|
|
|
|
template <typename Ret, typename... Args>
|
|
struct m3_signature
|
|
{
|
|
//不支持返回值的引用
|
|
static_assert(!std::is_reference<Ret>::value, "");
|
|
|
|
static const char* get()
|
|
{
|
|
static char value[] = {m3_type_to_sig<Ret>::value, '(', m3_type_to_sig<Args>::value..., ')', 0};
|
|
return (const char*) value;
|
|
}
|
|
};
|
|
//记录不同类型的指针,再wasm存的类型
|
|
template <typename T, typename = void>
|
|
struct _wasm_pointer_support_ptr_in_wasm;
|
|
|
|
template <typename T>
|
|
struct _wasm_pointer_support_ptr_in_wasm<T, typename std::enable_if<std::is_base_of<UObject, T>::value>::type>
|
|
{
|
|
using type = UObjectBase*;
|
|
};
|
|
|
|
template <typename T>
|
|
struct _wasm_pointer_support_ptr_in_wasm<T, typename std::enable_if<!std::is_base_of<UObject, T>::value>::type>
|
|
{
|
|
using type = void*;
|
|
};
|
|
|
|
template <typename T>
|
|
struct wasm_pointer_support_ptr_in_wasm
|
|
{
|
|
using type = typename _wasm_pointer_support_ptr_in_wasm<
|
|
typename std::remove_pointer<typename wasm_remove_const_ref<T>::type>::type>::type;
|
|
};
|
|
|
|
//指针
|
|
template <typename T, typename memstack_t = typename std::add_pointer_t<typename std::remove_reference_t<T>>,
|
|
typename t_remove_pointer = typename std::remove_pointer<T>::type>
|
|
typename std::enable_if<wasm_is_support_pointer_type<T>::value, int>::type wasm_link_get_args_from_stack(
|
|
IM3Runtime rt, IM3ImportContext _ctx, wasm_stack_type _sp, wasm_mem_type _mem, memstack_t& stack_ptr, int index)
|
|
{
|
|
using ptr_type_in_wasm = typename wasm_pointer_support_ptr_in_wasm<T>::type;
|
|
WASM_PTR offset = *((WASM_PTR*) (_sp + index));
|
|
ptr_type_in_wasm* tmp = (ptr_type_in_wasm*) m3ApiOffsetToPtr(offset);
|
|
*stack_ptr = static_cast<T>(*tmp);
|
|
return 0;
|
|
}
|
|
|
|
//简单类型,非引用
|
|
template <typename T, typename memstack_t = typename std::add_pointer_t<typename std::remove_reference_t<T>>>
|
|
typename std::enable_if<wasm_is_simple_type<T>::value && !std::is_reference<T>::value, int>::type wasm_link_get_args_from_stack(
|
|
IM3Runtime rt, IM3ImportContext _ctx, wasm_stack_type _sp, wasm_mem_type _mem, memstack_t& stack_ptr, int index)
|
|
{
|
|
T tmp = *((T*) (_sp + index));
|
|
*stack_ptr = tmp;
|
|
return 0;
|
|
}
|
|
|
|
//简单类型引用
|
|
template <typename T, typename memstack_t = typename std::add_pointer_t<typename std::remove_reference_t<T>>>
|
|
typename std::enable_if<wasm_is_simple_type<T>::value && std::is_reference<T>::value, int>::type wasm_link_get_args_from_stack(
|
|
IM3Runtime rt, IM3ImportContext _ctx, wasm_stack_type _sp, wasm_mem_type _mem, memstack_t& stack_ptr, int index)
|
|
{
|
|
using T_noRef = typename std::remove_reference_t<T>;
|
|
WASM_PTR offset = *((WASM_PTR*) (_sp + index));
|
|
T_noRef* tmp = (T_noRef*) m3ApiOffsetToPtr(offset);
|
|
stack_ptr = tmp;
|
|
return 0;
|
|
}
|
|
|
|
//复杂类型
|
|
template <typename T, typename memstack_t = typename std::add_pointer_t<typename std::remove_reference_t<T>>>
|
|
typename std::enable_if<wasm_is_complex_type<T>::value, int>::type wasm_link_get_args_from_stack(
|
|
IM3Runtime rt, IM3ImportContext _ctx, wasm_stack_type _sp, wasm_mem_type _mem, memstack_t& stack_ptr, int index)
|
|
{
|
|
using T_noRef = typename std::remove_reference_t<T>;
|
|
WASM_PTR offset = *((WASM_PTR*) (_sp + index));
|
|
T_noRef* tmp = (T_noRef*) m3ApiOffsetToPtr(offset);
|
|
stack_ptr = tmp;
|
|
return 0;
|
|
}
|
|
|
|
template <typename Func, Func* func>
|
|
struct wasm_link_helper;
|
|
|
|
template <typename Ret, typename... Args, Ret (*func)(Args...)>
|
|
struct wasm_link_helper<Ret(Args...), func>
|
|
{
|
|
template <typename X>
|
|
struct Functor;
|
|
|
|
template <int... Index>
|
|
struct Functor<std::index_sequence<Index...>>
|
|
{
|
|
//返回值是指针
|
|
//规避malloc,需要link的函数,返回值禁止是指针
|
|
/*template<class T>
|
|
static typename std::enable_if<wasm_is_support_pointer_type<T>::value && !std::is_same<T, void>::value, const void*>::type
|
|
_InternalInvoke(IM3Runtime rt, IM3ImportContext _ctx, wasm_stack_type _sp, wasm_mem_type _mem)
|
|
{
|
|
m3ApiReturnType(WASM_PTR);
|
|
auto stack_mem = std::make_tuple<typename std::remove_reference_t<Args>...>(typename
|
|
std::remove_reference_t<Args>()...); auto parm = std::make_tuple<typename std::add_pointer_t<typename
|
|
std::remove_reference_t<Args>>...>(&std::get<Index>(stack_mem)...); auto tmp =
|
|
std::make_tuple(wasm_link_get_args_from_stack<Args>(rt, _ctx, _sp, _mem, std::get<Index>(parm), Index)...);
|
|
//_sp += sizeof...(Args);
|
|
using T_RemoveConst = typename wasm_remove_const_ref<T>::type;
|
|
T_RemoveConst r = (T_RemoveConst)func(*std::get<Index>(parm)...);
|
|
WASM_PTR ptr = TryGetWasmPointerWithObject(r, rt);
|
|
{
|
|
*raw_return = ptr;
|
|
return nullptr;
|
|
}
|
|
}*/
|
|
|
|
//没有返回值
|
|
template <class T>
|
|
static typename std::enable_if<std::is_same<T, void>::value, void>::type _InternalInvoke(
|
|
IM3Runtime rt, IM3ImportContext _ctx, wasm_stack_type _sp, wasm_mem_type _mem)
|
|
{
|
|
auto stack_mem =
|
|
std::make_tuple<typename std::remove_reference_t<Args>...>(typename std::remove_reference_t<Args>()...);
|
|
auto parm = std::make_tuple<typename std::add_pointer_t<typename std::remove_reference_t<Args>>...>(
|
|
&std::get<Index>(stack_mem)...);
|
|
auto tmp = std::make_tuple(wasm_link_get_args_from_stack<Args>(rt, _ctx, _sp, _mem, std::get<Index>(parm), Index)...);
|
|
//_sp不是引用,所以也不用加了
|
|
//_sp += sizeof...(Args);
|
|
func(*std::get<Index>(parm)...);
|
|
return nullptr;
|
|
}
|
|
//返回值是复杂类型
|
|
template <class T>
|
|
static typename std::enable_if<wasm_is_complex_type<T>::value && !std::is_same<T, void>::value, const void*>::type
|
|
_InternalInvoke(IM3Runtime rt, IM3ImportContext _ctx, wasm_stack_type _sp, wasm_mem_type _mem)
|
|
{
|
|
using T_RemoveConst = typename wasm_remove_const_ref<T>::type;
|
|
m3ApiReturnType(WASM_PTR);
|
|
T_RemoveConst* ptr = (T_RemoveConst*) m3ApiOffsetToPtr(*raw_return);
|
|
|
|
auto stack_mem =
|
|
std::make_tuple<typename std::remove_reference_t<Args>...>(typename std::remove_reference_t<Args>()...);
|
|
auto parm = std::make_tuple<typename std::add_pointer_t<typename std::remove_reference_t<Args>>...>(
|
|
&std::get<Index>(stack_mem)...);
|
|
auto tmp = std::make_tuple(wasm_link_get_args_from_stack<Args>(rt, _ctx, _sp, _mem, std::get<Index>(parm), Index)...);
|
|
//_sp += sizeof...(Args);
|
|
|
|
*ptr = func(*std::get<Index>(parm)...);
|
|
|
|
return nullptr;
|
|
}
|
|
//返回值是简单类型
|
|
template <class T>
|
|
static typename std::enable_if<wasm_is_simple_type<T>::value && !std::is_same<T, void>::value, const void*>::type
|
|
_InternalInvoke(IM3Runtime rt, IM3ImportContext _ctx, wasm_stack_type _sp, wasm_mem_type _mem)
|
|
{
|
|
m3ApiReturnType(T);
|
|
auto stack_mem =
|
|
std::make_tuple<typename std::remove_reference_t<Args>...>(typename std::remove_reference_t<Args>()...);
|
|
auto parm = std::make_tuple<typename std::add_pointer_t<typename std::remove_reference_t<Args>>...>(
|
|
&std::get<Index>(stack_mem)...);
|
|
auto tmp = std::make_tuple(wasm_link_get_args_from_stack<Args>(rt, _ctx, _sp, _mem, std::get<Index>(parm), Index)...);
|
|
//_sp += sizeof...(Args);
|
|
|
|
T r = func(*std::get<Index>(parm)...);
|
|
{
|
|
*raw_return = r;
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
static const void* Invoke(IM3Runtime rt, IM3ImportContext _ctx, wasm_stack_type _sp, wasm_mem_type _mem)
|
|
{
|
|
return _InternalInvoke<Ret>(rt, _ctx, _sp, _mem);
|
|
}
|
|
};
|
|
};
|
|
|
|
template <typename Func, Func* func>
|
|
struct wasm_link_wrapper;
|
|
|
|
template <typename Ret, typename... Args, Ret (*func)(Args...)>
|
|
struct wasm_link_wrapper<Ret(Args...), func>
|
|
{
|
|
//为了规避malloc,暂时禁止返回值是指针的函数link
|
|
/*template<typename T>
|
|
static typename std::enable_if<wasm_is_support_pointer_type<T>::value && !std::is_same<T, void>::value, bool>::type
|
|
InternalLink(IM3Module _module, const char* const function_name)
|
|
{
|
|
//返回值不能是引用
|
|
static_assert(!std::is_reference<Ret>::value, "");
|
|
return Export_m3_LinkRawFunctionEx(_module, "*", function_name, m3_signature<Ret, Args...>::get(),
|
|
&wasm_link_helper<Ret(Args...), func>::template Functor<std::make_index_sequence<sizeof...(Args)>>::Invoke, nullptr);
|
|
}*/
|
|
|
|
template <typename T>
|
|
static typename std::enable_if<std::is_same<T, void>::value, bool>::type InternalLink(
|
|
IM3Module _module, const char* const function_name)
|
|
{
|
|
return Export_m3_LinkRawFunctionEx(_module, "*", function_name, m3_signature<void, Args...>::get(),
|
|
&wasm_link_helper<void(Args...), func>::template Functor<std::make_index_sequence<sizeof...(Args)>>::Invoke, nullptr);
|
|
}
|
|
|
|
template <typename T>
|
|
static typename std::enable_if<wasm_is_simple_type<T>::value && !std::is_same<T, void>::value, bool>::type InternalLink(
|
|
IM3Module _module, const char* const function_name)
|
|
{
|
|
//返回值不能是引用
|
|
static_assert(!std::is_reference<Ret>::value, "");
|
|
return Export_m3_LinkRawFunctionEx(_module, "*", function_name, m3_signature<Ret, Args...>::get(),
|
|
&wasm_link_helper<Ret(Args...), func>::template Functor<std::make_index_sequence<sizeof...(Args)>>::Invoke, nullptr);
|
|
}
|
|
|
|
template <typename T>
|
|
static typename std::enable_if<wasm_is_complex_type<T>::value && !std::is_same<T, void>::value, bool>::type InternalLink(
|
|
IM3Module _module, const char* const function_name)
|
|
{
|
|
//返回值不能是引用
|
|
static_assert(!std::is_reference<Ret>::value, "");
|
|
return Export_m3_LinkRawFunctionEx(_module, "*", function_name, m3_signature<void, Ret&, Args...>::get(),
|
|
&wasm_link_helper<Ret(Args...), func>::template Functor<std::make_index_sequence<sizeof...(Args)>>::Invoke, nullptr);
|
|
}
|
|
|
|
static bool link(IM3Module _module, const char* const function_name)
|
|
{
|
|
return InternalLink<Ret>(_module, function_name);
|
|
}
|
|
};
|