1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 18:37:34 +00:00

LibWasm: Implement reference instructions (ref.{null,func,is_null})

This commit is contained in:
Ali Mohammad Pur 2021-06-01 09:48:36 +04:30 committed by Ali Mohammad Pur
parent 7fb458b7c9
commit 56bf80251c
8 changed files with 73 additions and 9 deletions

View file

@ -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()) {

View file

@ -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;
}

View file

@ -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());
});

View file

@ -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;

View file

@ -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();
}