PkmnLib/src/ScriptResolving/WASM/WebAssemblyFunctionCall.hpp

108 lines
3.4 KiB
C++

#ifndef PKMNLIB_WEBASSEMBLYFUNCTIONCALL_H
#define PKMNLIB_WEBASSEMBLYFUNCTIONCALL_H
#include <Arbutils/Collections/List.hpp>
#include <Arbutils/Memory/Memory.hpp>
#include <wasm.h>
#include "wasm.h"
template <u32 argsCount, u32 returnsCount>
class WebAssemblyFunctionCall {
public:
WebAssemblyFunctionCall(const ArbUt::BorrowedPtr<wasm_func_t>& func) : _func(func) {}
NO_COPY_OR_MOVE(WebAssemblyFunctionCall)
void Call() {
wasm_val_vec_t args = {argsCount, _arguments.Data};
wasm_val_vec_t results;
if constexpr (returnsCount > 0) {
results = {returnsCount, _results.Data};
} else {
results = WASM_EMPTY_VEC;
}
auto* result = wasm_func_call(_func, &args, &results);
if (result != nullptr) {
wasm_message_t retrieved_message;
wasm_trap_message(result, &retrieved_message);
auto msg = std::string(retrieved_message.data, retrieved_message.size);
THROW(msg);
}
}
inline void Loadi32(size_t index, i32 value) { _arguments.Data[index] = WASM_I32_VAL(value); }
inline void Loadi64(size_t index, i64 value) { _arguments.Data[index] = WASM_I64_VAL(value); }
inline void Loadf32(size_t index, f32 value) { _arguments.Data[index] = WASM_F32_VAL(value); }
inline void Loadf64(size_t index, f64 value) { _arguments.Data[index] = WASM_F64_VAL(value); }
template <class T> inline void LoadExternRef(size_t index, T* value) {
_arguments.Data[index] = WASM_I64_VAL(reinterpret_cast<i64>(value));
}
[[nodiscard]] inline i32 GetResultAsi32() const {
if constexpr (returnsCount > 0) {
Ensure(_results.Data[0].kind == WASM_I32);
return _results.Data[0].of.i32;
} else {
return 0;
}
}
[[nodiscard]] inline i64 GetResultAsi64() const {
if constexpr (returnsCount > 0) {
Ensure(_results.Data[0].kind == WASM_I64);
return _results.Data[0].of.i64;
} else {
return 0;
}
}
[[nodiscard]] inline f32 GetResultAsf32() const {
if constexpr (returnsCount > 0) {
Ensure(_results.Data[0].kind == WASM_F32);
return _results.Data[0].of.f32;
} else {
return 0;
}
}
[[nodiscard]] inline f64 GetResultAsf64() const {
if constexpr (returnsCount > 0) {
Ensure(_results.Data[0].kind == WASM_F64);
return _results.Data[0].of.f64;
} else {
return 0;
}
}
template <class T> [[nodiscard]] inline T* GetResultAsExternRef() const {
if constexpr (returnsCount > 0) {
Ensure(_results.Data[0].kind == WASM_ANYREF);
return reinterpret_cast<T*>(_results.Data[0].of.i64);
} else {
return 0;
}
}
inline const wasm_val_t* GetRawResults() const {
if constexpr (returnsCount > 0) {
return _results.Data;
} else {
return 0;
}
}
private:
ArbUt::BorrowedPtr<wasm_func_t> _func;
struct Empty {};
template <u32 size> struct NonEmpty { wasm_val_t Data[size]; };
typedef typename std::conditional<argsCount == 0, Empty, NonEmpty<argsCount>>::type args_t;
typedef typename std::conditional<returnsCount == 0, Empty, NonEmpty<returnsCount>>::type result_t;
args_t _arguments;
result_t _results;
};
#endif // PKMNLIB_WEBASSEMBLYFUNCTIONCALL_H