This commit is contained in:
2025-02-10 00:44:11 +08:00
parent ece733c0e5
commit 1e0c4b8d8c
1640 changed files with 1628924 additions and 0 deletions
@@ -0,0 +1,18 @@
/*
* 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 "CoreMinimal.h"
#include "wasm3.h"
#include "m3_env.h"
// true表示成功,false表示失败
WASMCORE_API bool Export_m3_GetResults(IM3Function i_function, uint32_t i_retc, const void* o_retptrs[]);
WASMCORE_API bool Export_m3_Call(IM3Function i_function, uint32_t i_argc, const void* i_argptrs[]);
WASMCORE_API bool Export_m3_LinkRawFunctionEx(IM3Module io_module, const char* const i_moduleName, const char* const i_functionName,
const char* const i_signature, M3RawCall i_function, const void* i_userdata);
@@ -0,0 +1,501 @@
/*
* 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);
}
};
@@ -0,0 +1,13 @@
/*
* 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 "CoreMinimal.h"
#include "wasm3.h"
#include "m3_env.h"
#define WASM_PTR u32
@@ -0,0 +1,19 @@
/*
* 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 "CoreMinimal.h"
#include "Modules/ModuleManager.h"
class WasmCoreModule : public IModuleInterface
{
public:
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
@@ -0,0 +1,25 @@
/*
* 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 "CoreMinimal.h"
#include "WasmCommonIncludes.h"
class WASMCORE_API WasmEnv final
{
private:
IM3Environment _Env;
public:
WasmEnv();
~WasmEnv();
FORCEINLINE IM3Environment GetEnv()
{
return _Env;
}
};
@@ -0,0 +1,357 @@
/*
* 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 "CoreMinimal.h"
#include "wasm3.h"
#include "m3_env.h"
#include "WasmBindingTemplate.hpp"
#include "WasmRuntime.h"
#include "Wasm3ExportDef.h"
class WASMCORE_API WasmFunction final
{
private:
M3Function* _Function;
public:
WasmFunction(M3Function* Func) : _Function(Func)
{
}
FORCEINLINE M3Function* GetFunction() const
{
return _Function;
}
private:
template <typename Ret, typename... Args>
struct CallHelper
{
//不支持返回值是引用
static_assert(!std::is_reference<Ret>::value, "");
template <typename X>
struct Functor;
template <int... Index>
struct Functor<std::index_sequence<Index...>>
{
static bool InvokeNoReturn(WasmFunction* Outer, Args... args)
{
static_assert(wasm_is_all_support_type<Args...>::value, "");
WasmRuntime* Runtime = Outer->GetRuntime();
WasmStackAllocCacheInfo Backup = Runtime->GetCurrentStackAllocInfo();
auto stack_params = std::make_tuple<typename wasm_call_params_translator<Args>::translated_type...>(
typename wasm_call_params_translator<Args>::translated_type()...);
void* args_pointer[sizeof...(args)] = {Outer->InternalTranslatePointer<Args>(
&std::get<Index>(stack_params), (typename wasm_remove_const_ref<Args>::type*) &args)...};
if (Outer->CallWithArgsNoReturn(sizeof...(args), (const void**) args_pointer))
{
const WASM_PTR free_ptr_list[sizeof...(args)] = {
Outer->InternalCopyback<Args>(args_pointer[Index], (typename wasm_remove_const_ref<Args>::type*) &args)...};
Runtime->RestoreCurrentStackAllocInfo(Backup);
return true;
}
else
{
Runtime->RestoreCurrentStackAllocInfo(Backup);
return false;
}
}
//没有返回值
template <typename T>
static typename std::enable_if<std::is_same<T, void>::value, void>::type InnerInvoke(WasmFunction* Outer, Args... args)
{
InvokeNoReturn(Outer, std::forward<Args>(args)...);
}
// 返回值是复杂类型
template <typename T>
static typename std::enable_if<wasm_is_complex_type<T>::value, T>::type InnerInvoke(WasmFunction* Outer, Args... args)
{
static_assert(wasm_is_all_support_type<Args...>::value, "");
WasmRuntime* Runtime = Outer->GetRuntime();
WasmStackAllocCacheInfo Backup = Runtime->GetCurrentStackAllocInfo();
//复杂类型,栈的第一个是类型地址
WASM_PTR inner_ptr = Runtime->AllocStackParam(sizeof(T)).PtrInWasm;
auto stack_params = std::make_tuple<typename wasm_call_params_translator<Args>::translated_type...>(
typename wasm_call_params_translator<Args>::translated_type()...);
void* args_pointer[1 + sizeof...(args)] = {
(void*) &inner_ptr, Outer->InternalTranslatePointer<Args>(&std::get<Index>(stack_params),
(typename wasm_remove_const_ref<Args>::type*) &args)...};
if (Outer->CallWithArgsNoReturn(1 + sizeof...(args), (const void**) args_pointer))
{
const WASM_PTR free_ptr_list[1 + sizeof...(args)] = {inner_ptr,
Outer->InternalCopyback<Args>(args_pointer[Index], (typename wasm_remove_const_ref<Args>::type*) &args)...};
Ret* ret_ptr = (Ret*) Runtime->GetPlatformAddress(inner_ptr);
Ret r = *ret_ptr;
Runtime->RestoreCurrentStackAllocInfo(Backup);
return r;
}
else
{
Runtime->RestoreCurrentStackAllocInfo(Backup);
return T();
}
}
//返回值是简单类型
template <typename T>
static typename std::enable_if<wasm_is_simple_type<T>::value, T>::type InnerInvoke(WasmFunction* Outer, Args... args)
{
static_assert(wasm_is_all_support_type<Args...>::value, "");
WasmRuntime* Runtime = Outer->GetRuntime();
WasmStackAllocCacheInfo Backup = Runtime->GetCurrentStackAllocInfo();
auto stack_params = std::make_tuple<typename wasm_call_params_translator<Args>::translated_type...>(
typename wasm_call_params_translator<Args>::translated_type()...);
void* args_pointer[sizeof...(args)] = {Outer->InternalTranslatePointer<Args>(
&std::get<Index>(stack_params), (typename wasm_remove_const_ref<Args>::type*) &args)...};
if (Outer->CallWithArgsNoReturn(sizeof...(args), (const void**) args_pointer))
{
const WASM_PTR free_ptr_list[sizeof...(args)] = {
Outer->InternalCopyback<Args>(args_pointer[Index], (typename wasm_remove_const_ref<Args>::type*) &args)...};
T r = Outer->GetReturnValue<T>();
Runtime->RestoreCurrentStackAllocInfo(Backup);
return r;
}
else
{
Runtime->RestoreCurrentStackAllocInfo(Backup);
return T();
}
}
// 返回值是指针,等价于先返回一个wasm_ptr,再解析这个wasm_ptr
template <typename T>
static typename std::enable_if<wasm_is_support_pointer_type<T>::value, T>::type InnerInvoke(
WasmFunction* Outer, Args... args)
{
using ptr_type_in_wasm = typename wasm_pointer_support_ptr_in_wasm<T>::type;
WASM_PTR ptr = InnerInvoke<WASM_PTR>(Outer, std::forward<Args>(args)...);
ptr_type_in_wasm* realPtr = (ptr_type_in_wasm*) Outer->GetRuntime()->GetPlatformAddress(ptr);
return static_cast<T>(*realPtr);
}
static Ret Invoke(WasmFunction* Outer, Args... args)
{
return InnerInvoke<Ret>(Outer, std::forward<Args>(args)...);
}
};
};
public:
//内部接口,谨慎调用
bool CallWithArgsNoReturn(int arg_count, const void** args) const
{
check(_Function);
if (!Export_m3_Call(_Function, arg_count, args))
{
UE_LOG(LogTemp, Error, TEXT("Error In Call Simple Function %s"), ANSI_TO_TCHAR(_Function->export_name));
return false;
}
return true;
}
//简单类型返回值
template <typename Ret>
typename std::enable_if<wasm_is_simple_type<Ret>::value, Ret>::type GetReturnValue() const
{
//不支持返回值是引用
static_assert(!std::is_reference<Ret>::value, "");
Ret r;
void* ret_ptrs[] = {&r};
if (!Export_m3_GetResults(_Function, 1, (const void**) ret_ptrs))
{
UE_LOG(LogTemp, Error, TEXT("Error In GetReturnValue %s"), ANSI_TO_TCHAR(_Function->export_name));
}
return r;
}
//并不支持复杂类型返回值使用这个接口,直接使用Call,因为复杂类型的返回值传参不太一样,这里只考虑指针和简单类型
template <typename Ret>
typename std::enable_if<wasm_is_support_pointer_type<Ret>::value, Ret>::type GetReturnValue() const
{
//不支持返回值是引用
static_assert(!std::is_reference<Ret>::value, "");
using ptr_type_in_wasm = typename wasm_pointer_support_ptr_in_wasm<Ret>::type;
WASM_PTR r;
void* ret_ptrs[] = {&r};
if (!Export_m3_GetResults(_Function, 1, (const void**) ret_ptrs))
{
UE_LOG(LogTemp, Error, TEXT("Error In GetReturnValue %s"), ANSI_TO_TCHAR(_Function->export_name));
}
ptr_type_in_wasm* ptr = (ptr_type_in_wasm*) GetRuntime()->GetPlatformAddress(r);
return static_cast<Ret>(*ptr);
}
template <typename... Args>
bool CallNoReturn(Args... args)
{
// todo 看看是否需要把栈补一下,要不然可能会不平衡?
return CallHelper<void, Args...>::template Functor<std::make_index_sequence<sizeof...(Args)>>::InvokeNoReturn(
this, std::forward<Args>(args)...);
}
bool CallNoReturn()
{
return CallWithArgsNoReturn(0, nullptr);
}
template <typename Ret, typename... Args>
Ret Call(Args... args)
{
return CallHelper<Ret, Args...>::template Functor<std::make_index_sequence<sizeof...(Args)>>::Invoke(
this, std::forward<Args>(args)...);
}
//简单类型或者指针类型
template <typename Ret>
typename std::enable_if<wasm_is_simple_type<Ret>::value || wasm_is_support_pointer_type<Ret>::value, Ret>::type Call()
{
//不支持返回值是引用
static_assert(!std::is_reference<Ret>::value, "");
if (CallWithArgsNoReturn(0, nullptr))
{
return GetReturnValue<Ret>();
}
return Ret();
}
//复杂类型
template <typename Ret>
typename std::enable_if<wasm_is_complex_type<Ret>::value, Ret>::type Call()
{
//不支持返回值是引用
static_assert(!std::is_reference<Ret>::value, "");
WasmRuntime* Runtime = GetRuntime();
WasmStackAllocCacheInfo Backup = Runtime->GetCurrentStackAllocInfo();
WASM_PTR inner_ptr = Runtime->AllocStackParam(sizeof(Ret)).PtrInWasm;
void* args_pointer[] = {
&inner_ptr,
};
if (CallWithArgsNoReturn(1, (const void**) args_pointer))
{
Ret* ptr = (Ret*) Runtime->GetPlatformAddress(inner_ptr);
Ret r = *ptr;
Runtime->RestoreCurrentStackAllocInfo(Backup);
return r;
}
else
{
Runtime->RestoreCurrentStackAllocInfo(Backup);
}
return Ret();
}
private:
// 简单类型,非引用
template <typename T, typename T_Translatedtype = typename wasm_call_params_translator<T>::translated_type,
typename RT = typename wasm_remove_const_ref<T>::type>
typename std::enable_if<wasm_is_simple_type<T>::value && !std::is_reference<T>::value, void*>::type InternalTranslatePointer(
T_Translatedtype* stack_pointer, RT* src_pointer)
{
//非引用的,直接使用原来的地址就好了,因为本来就是传值的语义
return (void*) src_pointer;
}
// 简单类型的引用
template <typename T, typename T_Translatedtype = typename wasm_call_params_translator<T>::translated_type,
typename RT = typename wasm_remove_const_ref<T>::type>
typename std::enable_if<wasm_is_simple_type<T>::value && std::is_reference<T>::value, void*>::type InternalTranslatePointer(
T_Translatedtype* stack_pointer, RT* src_pointer)
{
//引用被wasm当作指针来传递
WasmRuntime* Runtime = GetRuntime();
WasmStackAllocCacheInfo NewMalloc = Runtime->AllocStackParam(sizeof(T));
FMemory::Memcpy(NewMalloc.RealPtr, src_pointer, sizeof(T));
*((WASM_PTR*) stack_pointer) = NewMalloc.PtrInWasm;
return stack_pointer;
}
// 复杂类型
template <typename T, typename T_Translatedtype = typename wasm_call_params_translator<T>::translated_type,
typename RT = typename wasm_remove_const_ref<T>::type>
typename std::enable_if<wasm_is_complex_type<T>::value, void*>::type InternalTranslatePointer(
void* stack_pointer, RT* src_pointer)
{
static_assert(std::is_same<T_Translatedtype, WASM_PTR>::value, "");
WasmRuntime* Runtime = GetRuntime();
WasmStackAllocCacheInfo NewMalloc = Runtime->AllocStackParam(sizeof(T));
FMemory::Memcpy(NewMalloc.RealPtr, src_pointer, sizeof(T));
*((WASM_PTR*) stack_pointer) = NewMalloc.PtrInWasm;
return stack_pointer;
}
//指针
template <typename T, typename T_Translatedtype = typename wasm_call_params_translator<T>::translated_type,
typename RT = typename wasm_remove_const_ref<T>::type>
typename std::enable_if<wasm_is_support_pointer_type<T>::value, void*>::type InternalTranslatePointer(
void* stack_pointer, RT* src_pointer)
{
WasmRuntime* Runtime = GetRuntime();
WasmStackAllocCacheInfo NewMalloc = Runtime->AllocStackParam(sizeof(void*));
T_Translatedtype value = static_cast<T_Translatedtype>(*src_pointer);
*((T_Translatedtype*) (NewMalloc.RealPtr)) = value;
*((WASM_PTR*) stack_pointer) = NewMalloc.PtrInWasm;
return stack_pointer;
}
template <typename T, typename T_Translatedtype = typename wasm_call_params_translator<T>::translated_type,
typename RT = typename wasm_remove_const_ref<T>::type>
typename std::enable_if<wasm_is_support_pointer_type<T>::value, WASM_PTR>::type InternalCopyback(
void* stack_pointer, RT* src_pointer)
{
// 指针也啥都不用干
return 0;
}
template <typename T, typename T_Translatedtype = typename wasm_call_params_translator<T>::translated_type,
typename RT = typename wasm_remove_const_ref<T>::type>
typename std::enable_if<wasm_is_simple_type<T>::value && !std::is_reference<T>::value, WASM_PTR>::type InternalCopyback(
void* stack_pointer, RT* src_pointer)
{
// 非引用的简单类型,啥都不用干
return 0;
}
template <typename T, typename T_Translatedtype = typename wasm_call_params_translator<T>::translated_type,
typename RT = typename wasm_remove_const_ref<T>::type>
typename std::enable_if<wasm_is_simple_type<T>::value && std::is_reference<T>::value, WASM_PTR>::type InternalCopyback(
void* stack_pointer, RT* src_pointer)
{
// 引用的简单类型,还要把值拷贝回去
WASM_PTR ptr = *((WASM_PTR*) stack_pointer);
WasmRuntime* Runtime = GetRuntime();
if (std::is_reference<T>::value && !std::is_const<typename std::remove_reference<T>::type>::value)
{
void* real_ptr = Runtime->GetPlatformAddress(ptr);
FMemory::Memcpy((void*) src_pointer, real_ptr, sizeof(T));
}
return ptr;
}
template <typename T, typename T_Translatedtype = typename wasm_call_params_translator<T>::translated_type,
typename RT = typename wasm_remove_const_ref<T>::type>
typename std::enable_if<wasm_is_complex_type<T>::value, WASM_PTR>::type InternalCopyback(void* stack_pointer, RT* src_pointer)
{
static_assert(std::is_same<T_Translatedtype, WASM_PTR>::value, "");
WASM_PTR ptr = *((WASM_PTR*) stack_pointer);
WasmRuntime* Runtime = GetRuntime();
if (std::is_reference<T>::value && !std::is_const<typename std::remove_reference<T>::type>::value)
{
void* real_ptr = Runtime->GetPlatformAddress(ptr);
FMemory::Memcpy((void*) src_pointer, real_ptr, sizeof(T));
}
return ptr;
}
FORCEINLINE WasmRuntime* GetRuntime() const
{
return (WasmRuntime*) _Function->module->runtime->userdata;
}
};
@@ -0,0 +1,12 @@
/*
* 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 "CoreMinimal.h"
#include "wasm3.h"
#include "WasmEnv.h"
@@ -0,0 +1,51 @@
/*
* 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 "CoreMinimal.h"
#include "wasm3.h"
#include "m3_env.h"
#include "WasmCommonIncludes.h"
#include <functional>
class WasmRuntime;
class WasmFunction;
class WasmEnv;
using AdditionLinkFunc = std::function<bool(IM3Module)>;
class WASMCORE_API WasmModuleInstance final
{
private:
IM3Module _Module;
TMap<FName, WasmFunction*> _AllExportFunctions;
TArray<uint8> Data;
public:
WasmModuleInstance(TArray<uint8>& InData);
int Index = -1;
bool ParseModule(WasmEnv* Env);
bool LoadModule(WasmRuntime* Runtime, int LinkCategory, AdditionLinkFunc _Func = nullptr);
size_t TableGrow(size_t N) const;
void TableSet(size_t Idx, IM3Function Function) const;
size_t TableLen() const;
~WasmModuleInstance();
const TMap<FName, WasmFunction*>& GetAllExportFunctions()
{
return _AllExportFunctions;
}
IM3Module GetModule()
{
return _Module;
}
};
@@ -0,0 +1,89 @@
/*
* 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 "CoreMinimal.h"
#include "WasmCommonIncludes.h"
#include "WasmEnv.h"
class WasmModuleInstance;
class WasmFunction;
class WasmPointerSupport;
struct WASMCORE_API WasmStackAllocCacheInfo
{
WASM_PTR PtrInWasm = 0;
char* RealPtr = nullptr;
};
class WASMCORE_API WasmRuntime final
{
private:
WasmEnv* _Env;
IM3Runtime _Runtime;
TArray<WasmModuleInstance*> _AllModuleInstances;
uint16 _RuntimeSeq;
WasmStackAllocCacheInfo CurrentStackAllocInfo;
WasmStackAllocCacheInfo BaseStackAllocInfo;
WASM_PTR MaxWasmStackAllocCount = 0;
public:
WasmEnv* GetEnv()
{
return _Env;
}
WasmStackAllocCacheInfo GetCurrentStackAllocInfo()
{
return CurrentStackAllocInfo;
}
WasmStackAllocCacheInfo AllocStackParam(int Count)
{
WasmStackAllocCacheInfo ret = CurrentStackAllocInfo;
if (Count < 8)
Count = 8;
CurrentStackAllocInfo.PtrInWasm += Count;
CurrentStackAllocInfo.RealPtr += Count;
check(CurrentStackAllocInfo.PtrInWasm - BaseStackAllocInfo.PtrInWasm < MaxWasmStackAllocCount);
return ret;
}
void RestoreCurrentStackAllocInfo(const WasmStackAllocCacheInfo& NewInfo)
{
check(NewInfo.PtrInWasm >= BaseStackAllocInfo.PtrInWasm && NewInfo.RealPtr >= BaseStackAllocInfo.RealPtr);
CurrentStackAllocInfo = NewInfo;
}
WasmRuntime(WasmEnv* Env, int MaxPage = 10, int InitPage = 1, int StackSizeInBytes = 5 * 1024);
~WasmRuntime();
int Grow(int number);
uint8* GetBuffer(int& Length);
uint16 GetRuntimeSeq() const
{
return _RuntimeSeq;
}
WasmModuleInstance* GetModuleInstance(int index) const
{
return _AllModuleInstances[index];
}
WasmModuleInstance* OnModuleInstance(WasmModuleInstance* InModuleInstance);
FORCEINLINE IM3Runtime GetRuntime() const
{
return _Runtime;
}
//转换wasm与host的地址
void* GetPlatformAddress(WASM_PTR ptr);
static WasmRuntime* StaticGetWasmRuntime(IM3Runtime Runtime);
};
@@ -0,0 +1,41 @@
/*
* 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 "CoreMinimal.h"
#include "wasm3.h"
#include "m3_env.h"
#include "WasmBindingTemplate.hpp"
typedef bool (*WasmStaticLinkClassFunction)(IM3Module _Module);
class WASMCORE_API WasmStaticLinkClass
{
public:
WasmStaticLinkClass(WasmStaticLinkClassFunction func, int Category);
static bool Link(IM3Module _Module, int Category);
};
#define WASM_BEGIN_LINK_GLOBAL(GlobalID, Category) \
static bool _WASM_##GlobalID##_Link_##Category##_Func(IM3Module _Module) \
{
#define WASM_LINK_GLOBAL(Func) \
if (!wasm_link_wrapper<decltype(Func), Func>::link(_Module, #Func)) \
return false;
#define WASM_LINK_GLOBAL_WITH_NAME(Func, LinkName) \
if (!wasm_link_wrapper<decltype(Func), Func>::link(_Module, #LinkName)) \
return false;
#define WASM_END_LINK_GLOBAL(GlobalID, Category) \
return true; \
} \
; \
static WasmStaticLinkClass _WASM_##GlobalID##_Link_##Category##_Func_ExportMember( \
_WASM_##GlobalID##_Link_##Category##_Func, Category);