summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Tests/LibWasm/test-wasm.cpp9
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp3
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h20
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp4
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp25
-rw-r--r--Userland/Libraries/LibWasm/Types.h8
-rw-r--r--Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp5
-rw-r--r--Userland/Utilities/wasm.cpp8
8 files changed, 73 insertions, 9 deletions
diff --git a/Tests/LibWasm/test-wasm.cpp b/Tests/LibWasm/test-wasm.cpp
index 0ecd294ec6..ecd89f8932 100644
--- a/Tests/LibWasm/test-wasm.cpp
+++ b/Tests/LibWasm/test-wasm.cpp
@@ -190,6 +190,12 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyModule::wasm_invoke)
case Wasm::ValueType::Kind::ExternReference:
arguments.append(Wasm::Value(Wasm::ExternAddress { static_cast<u64>(value) }));
break;
+ case Wasm::ValueType::Kind::NullFunctionReference:
+ arguments.append(Wasm::Value(Wasm::Value::Null { Wasm::ValueType(Wasm::ValueType::Kind::FunctionReference) }));
+ break;
+ case Wasm::ValueType::Kind::NullExternReference:
+ arguments.append(Wasm::Value(Wasm::Value::Null { Wasm::ValueType(Wasm::ValueType::Kind::ExternReference) }));
+ break;
}
}
@@ -206,6 +212,7 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyModule::wasm_invoke)
result.values().first().value().visit(
[&](const auto& value) { return_value = JS::Value(static_cast<double>(value)); },
[&](const Wasm::FunctionAddress& index) { return_value = JS::Value(static_cast<double>(index.value())); },
- [&](const Wasm::ExternAddress& index) { return_value = JS::Value(static_cast<double>(index.value())); });
+ [&](const Wasm::ExternAddress& index) { return_value = JS::Value(static_cast<double>(index.value())); },
+ [&](const Wasm::Value::Null&) { return_value = JS::js_null(); });
return return_value;
}
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp
index 2daca7ab14..592c90223c 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp
+++ b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp
@@ -152,7 +152,8 @@ InstantiationResult AbstractMachine::instantiate(const Module& module, Vector<Ex
result.values().first().value().visit(
[&](const auto& value) { offset = value; },
[&](const FunctionAddress&) { instantiation_result = InstantiationError { "Data segment offset returned an address" }; },
- [&](const ExternAddress&) { instantiation_result = InstantiationError { "Data segment offset returned an address" }; });
+ [&](const ExternAddress&) { instantiation_result = InstantiationError { "Data segment offset returned an address" }; },
+ [&](const Value::Null&) { instantiation_result = InstantiationError { "Data segment offset returned a null reference" }; });
if (instantiation_result.has_value() && instantiation_result->is_error())
return;
if (main_module_instance.memories().size() <= data.index.value()) {
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h
index 98db12d9ab..b7b49b664b 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h
+++ b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h
@@ -45,7 +45,11 @@ public:
{
}
- using AnyValueType = Variant<i32, i64, float, double, FunctionAddress, ExternAddress>;
+ struct Null {
+ ValueType type;
+ };
+
+ using AnyValueType = Variant<i32, i64, float, double, FunctionAddress, ExternAddress, Null>;
explicit Value(AnyValueType value)
: m_value(move(value))
, m_type(ValueType::I32)
@@ -62,6 +66,8 @@ public:
m_type = ValueType { ValueType::FunctionReference };
else if (m_value.has<ExternAddress>())
m_type = ValueType { ValueType::ExternReference };
+ else if (m_value.has<Null>())
+ m_type = ValueType { m_value.get<Null>().type.kind() == ValueType::ExternReference ? ValueType::NullExternReference : ValueType::NullFunctionReference };
else
VERIFY_NOT_REACHED();
}
@@ -90,6 +96,14 @@ public:
case ValueType::Kind::F64:
m_value = bit_cast<double>(raw_value);
break;
+ case ValueType::Kind::NullFunctionReference:
+ VERIFY(raw_value == 0);
+ m_value = Null { ValueType(ValueType::Kind::FunctionReference) };
+ break;
+ case ValueType::Kind::NullExternReference:
+ VERIFY(raw_value == 0);
+ m_value = Null { ValueType(ValueType::Kind::ExternReference) };
+ break;
default:
VERIFY_NOT_REACHED();
}
@@ -139,6 +153,10 @@ public:
[&](const ExternAddress& address) {
if constexpr (IsSame<T, ExternAddress>)
result = address;
+ },
+ [&](const Null& null) {
+ if constexpr (IsSame<T, Null>)
+ result = null;
});
return result;
}
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp
index 4a27fcbd49..fcfd14ddee 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp
+++ b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp
@@ -85,6 +85,8 @@ void Configuration::dump_stack()
v.value().visit([]<typename T>(const T& v) {
if constexpr (IsIntegral<T> || IsFloatingPoint<T>)
dbgln(" {}", v);
+ else if constexpr (IsSame<Value::Null, T>)
+ dbgln(" *null");
else
dbgln(" *{}", v.value());
});
@@ -95,6 +97,8 @@ void Configuration::dump_stack()
local.value().visit([]<typename T>(const T& v) {
if constexpr (IsIntegral<T> || IsFloatingPoint<T>)
dbgln(" {}", v);
+ else if constexpr (IsSame<Value::Null, T>)
+ dbgln(" *null");
else
dbgln(" *{}", v.value());
});
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp b/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp
index efeec9a304..dbce68e6e7 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp
+++ b/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp
@@ -590,10 +590,29 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi
}
case Instructions::table_get.value():
case Instructions::table_set.value():
- case Instructions::ref_null.value():
- case Instructions::ref_func.value():
- case Instructions::ref_is_null.value():
goto unimplemented;
+ case Instructions::ref_null.value(): {
+ auto type = instruction.arguments().get<ValueType>();
+ TRAP_IF_NOT(type.is_reference());
+ configuration.stack().push(Value(Value::Null { type }));
+ return;
+ };
+ case Instructions::ref_func.value(): {
+ auto index = instruction.arguments().get<FunctionIndex>().value();
+ auto& functions = configuration.frame().module().functions();
+ TRAP_IF_NOT(functions.size() > index);
+ auto address = functions[index];
+ configuration.stack().push(Value(ValueType(ValueType::FunctionReference), address.value()));
+ return;
+ }
+ case Instructions::ref_is_null.value(): {
+ auto top = configuration.stack().peek().get_pointer<Value>();
+ TRAP_IF_NOT(top);
+ TRAP_IF_NOT(top->type().is_reference());
+ auto is_null = top->to<Value::Null>().has_value();
+ configuration.stack().peek() = Value(ValueType(ValueType::I32), static_cast<u64>(is_null ? 1 : 0));
+ return;
+ }
case Instructions::drop.value():
configuration.stack().pop();
return;
diff --git a/Userland/Libraries/LibWasm/Types.h b/Userland/Libraries/LibWasm/Types.h
index 9134af6272..bb0299b38a 100644
--- a/Userland/Libraries/LibWasm/Types.h
+++ b/Userland/Libraries/LibWasm/Types.h
@@ -170,6 +170,8 @@ public:
F64,
FunctionReference,
ExternReference,
+ NullFunctionReference,
+ NullExternReference,
};
explicit ValueType(Kind kind)
@@ -177,7 +179,7 @@ public:
{
}
- auto is_reference() const { return m_kind == ExternReference || m_kind == FunctionReference; }
+ auto is_reference() const { return m_kind == ExternReference || m_kind == FunctionReference || m_kind == NullExternReference || m_kind == NullFunctionReference; }
auto is_numeric() const { return !is_reference(); }
auto kind() const { return m_kind; }
@@ -198,6 +200,10 @@ public:
return "funcref";
case ExternReference:
return "externref";
+ case NullFunctionReference:
+ return "ref.null externref";
+ case NullExternReference:
+ return "ref.null funcref";
}
VERIFY_NOT_REACHED();
}
diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp
index a8e8f82c8c..b4bd033dc4 100644
--- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp
+++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp
@@ -262,7 +262,10 @@ JS::Value to_js_value(Wasm::Value& wasm_value, JS::GlobalObject& global_object)
case Wasm::ValueType::FunctionReference:
// FIXME: What's the name of a function reference that isn't exported?
return create_native_function(wasm_value.to<Wasm::FunctionAddress>().value(), "FIXME_IHaveNoIdeaWhatThisShouldBeCalled", global_object);
+ case Wasm::ValueType::NullFunctionReference:
+ return JS::js_null();
case Wasm::ValueType::ExternReference:
+ case Wasm::ValueType::NullExternReference:
TODO();
}
VERIFY_NOT_REACHED();
@@ -304,6 +307,8 @@ Optional<Wasm::Value> to_webassembly_value(JS::Value value, const Wasm::ValueTyp
}
case Wasm::ValueType::FunctionReference:
case Wasm::ValueType::ExternReference:
+ case Wasm::ValueType::NullFunctionReference:
+ case Wasm::ValueType::NullExternReference:
TODO();
}
diff --git a/Userland/Utilities/wasm.cpp b/Userland/Utilities/wasm.cpp
index f9a2d97dc5..5b1d7f786d 100644
--- a/Userland/Utilities/wasm.cpp
+++ b/Userland/Utilities/wasm.cpp
@@ -202,9 +202,11 @@ static bool pre_interpret_hook(Wasm::Configuration& config, Wasm::InstructionPoi
warnln("Returned:");
for (auto& value : result.values()) {
auto str = value.value().visit(
- [&](const auto& value) {
+ [&]<typename T>(const T& value) {
if constexpr (requires { value.value(); })
return String::formatted(" -> addr{} ", value.value());
+ else if constexpr (IsSame<Wasm::Value::Null, T>)
+ return String::formatted(" ->addr(null)");
else
return String::formatted(" -> {} ", value);
});
@@ -460,9 +462,11 @@ int main(int argc, char* argv[])
warnln("Returned:");
for (auto& value : result.values()) {
value.value().visit(
- [&](const auto& value) {
+ [&]<typename T>(const T& value) {
if constexpr (requires { value.value(); })
out(" -> addr{} ", value.value());
+ else if constexpr (IsSame<Wasm::Value::Null, T>)
+ out(" ->addr(null)");
else
out(" -> {} ", value);
});