87 lines
4.4 KiB
C++
87 lines
4.4 KiB
C++
#include "CoreMethods.hpp"
|
|
#include <cstring>
|
|
#include "../WebAssemblyScriptResolver.hpp"
|
|
#include "WasmHelperFile.hpp"
|
|
#include "wasm.h"
|
|
|
|
wasm_func_t* CreateErrorFunc(wasm_store_t* store, WebAssemblyScriptResolver* resolver) {
|
|
// This is probably the most horrific function we need to expose. As we do not want the scripting library to be
|
|
// responsible for string formatting for size reasons, we pass a lot of data separately. This includes several
|
|
// strings.
|
|
return WasmHelpers::CreateFunc<void, i32, i32, i32, i32, i32, i32>(
|
|
store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t*) -> wasm_trap_t* {
|
|
auto msg = args->data[0].of.i32;
|
|
auto msg_len = args->data[1].of.i32;
|
|
auto file = args->data[2].of.i32;
|
|
auto file_len = args->data[3].of.i32;
|
|
auto line = args->data[4].of.i32;
|
|
auto position = args->data[5].of.i32;
|
|
|
|
auto* resolver = (WebAssemblyScriptResolver*)env;
|
|
auto* msgPointer = wasm_memory_data(resolver->GetMemory()) + msg;
|
|
auto* filePointer = wasm_memory_data(resolver->GetMemory()) + file;
|
|
|
|
auto msgString = std::string_view(msgPointer, msg_len);
|
|
auto fileString = std::string_view(filePointer, file_len);
|
|
|
|
std::stringstream fullMessage;
|
|
fullMessage << "WASM Error with message: " << msgString << std::endl
|
|
<< "in file: " << fileString << ". Line: " << line << ":" << position;
|
|
|
|
wasm_message_t message;
|
|
wasm_name_new_from_string_nt(&message, fullMessage.str().c_str());
|
|
wasm_trap_t* trap = wasm_trap_new(resolver->GetStore(), &message);
|
|
wasm_name_delete(&message);
|
|
return trap;
|
|
});
|
|
}
|
|
|
|
wasm_func_t* CreatePrintFunc(wasm_store_t* store, WebAssemblyScriptResolver* resolver) {
|
|
return WasmHelpers::CreateFunc<void, i32, i32>(
|
|
store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t*) -> wasm_trap_t* {
|
|
auto msg = args->data[0].of.i32;
|
|
auto msg_len = args->data[1].of.i32;
|
|
auto resolver = (WebAssemblyScriptResolver*)env;
|
|
auto* msgPointer = wasm_memory_data(resolver->GetMemory()) + msg;
|
|
auto msgString = std::string_view(msgPointer, msg_len);
|
|
std::cout << msgString << std::endl;
|
|
return nullptr;
|
|
});
|
|
;
|
|
}
|
|
|
|
wasm_func_t* ConstString_GetHash(wasm_store_t* store, WebAssemblyScriptResolver* resolver) {
|
|
return WasmHelpers::CreateFunc2<u32, const ArbUt::StringView*>(
|
|
store, resolver,
|
|
std::function<u32(WebAssemblyScriptResolver*, const ArbUt::StringView*)>(
|
|
[](WebAssemblyScriptResolver*, const ArbUt::StringView* sv) -> u32 { return sv->GetHash(); }));
|
|
}
|
|
|
|
wasm_func_t* ConstString_GetStr(wasm_store_t* store, WebAssemblyScriptResolver* resolver) {
|
|
return WasmHelpers::CreateFunc<i32, const ArbUt::StringView*>(
|
|
store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t* returns) -> wasm_trap_t* {
|
|
auto resolver = (WebAssemblyScriptResolver*)env;
|
|
auto& constString = *(ArbUt::StringView*)args->data[0].of.i64;
|
|
|
|
// To allow webassembly to access the C String, we need to allocate it inside it's memory.
|
|
// Length + 1 to make room for the '\0'
|
|
auto stringPointer = resolver->AllocateMemory(constString.Length() + 1, std::alignment_of<const char>());
|
|
|
|
// After we have the pointer to the memory allocated for the string, copy the string with specified length
|
|
// to it, then suffix it with the null byte to end it.
|
|
strncpy(reinterpret_cast<char*>(stringPointer.first), constString.c_str(), constString.Length());
|
|
stringPointer.first[constString.Length()] = '\0';
|
|
|
|
returns->data[0] = WASM_I32_VAL(stringPointer.second);
|
|
return nullptr;
|
|
});
|
|
}
|
|
|
|
void WebAssemblyCoreMethods::Register(wasm_store_t* store, ArbUt::Dictionary<std::string, wasm_func_t*>& externs,
|
|
WebAssemblyScriptResolver* resolver) {
|
|
externs.Insert("_error", CreateErrorFunc(store, resolver));
|
|
externs.Insert("_print", CreatePrintFunc(store, resolver));
|
|
externs.Insert("arbutils_const_string_get_hash", ConstString_GetHash(store, resolver));
|
|
externs.Insert("arbutils_const_string_get_str", ConstString_GetStr(store, resolver));
|
|
}
|