summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWasm
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2021-06-04 03:27:51 +0430
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2021-06-04 16:07:42 +0430
commitc392a0cf7ffbad07c10021b9a3e97f5239b40c55 (patch)
tree024c13cb4168f1c44b7b0fd07519e557eaf024da /Userland/Libraries/LibWasm
parent9db418e1fb082db064d5daccbe73f7682207dac2 (diff)
downloadserenity-c392a0cf7ffbad07c10021b9a3e97f5239b40c55.zip
LibWasm: Implement the br.table instruction
Unlike its name, this instruction has nothing to do with tables, it's just a very simple switch-case instruction.
Diffstat (limited to 'Userland/Libraries/LibWasm')
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp3
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp15
2 files changed, 16 insertions, 2 deletions
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp
index fcfd14ddee..ac93f77507 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp
+++ b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp
@@ -66,6 +66,9 @@ Result Configuration::execute(Interpreter& interpreter)
if (interpreter.did_trap())
return Trap {};
+ if (stack().size() <= frame().arity() + 1)
+ return Trap {};
+
Vector<Value> results;
results.ensure_capacity(frame().arity());
for (size_t i = 0; i < frame().arity(); ++i)
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp b/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp
index afebe0ef97..6e625c7aa8 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp
+++ b/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp
@@ -122,6 +122,7 @@ void BytecodeInterpreter::call_address(Configuration& configuration, FunctionAdd
const FunctionType* type { nullptr };
instance->visit([&](const auto& function) { type = &function.type(); });
TRAP_IF_NOT(type);
+ TRAP_IF_NOT(configuration.stack().entries().size() > type->parameters().size());
Vector<Value> args;
args.ensure_capacity(type->parameters().size());
auto span = configuration.stack().entries().span().slice_from_end(type->parameters().size());
@@ -506,8 +507,18 @@ void BytecodeInterpreter::interpret(Configuration& configuration, InstructionPoi
return;
return branch_to_label(configuration, instruction.arguments().get<LabelIndex>());
}
- case Instructions::br_table.value():
- goto unimplemented;
+ case Instructions::br_table.value(): {
+ auto& arguments = instruction.arguments().get<Instruction::TableBranchArgs>();
+ auto entry = configuration.stack().pop();
+ TRAP_IF_NOT(entry.has<Value>());
+ auto maybe_i = entry.get<Value>().to<i32>();
+ TRAP_IF_NOT(maybe_i.has_value());
+ TRAP_IF_NOT(maybe_i.value() >= 0);
+ size_t i = *maybe_i;
+ if (i < arguments.labels.size())
+ return branch_to_label(configuration, arguments.labels[i]);
+ return branch_to_label(configuration, arguments.default_);
+ }
case Instructions::call.value(): {
auto index = instruction.arguments().get<FunctionIndex>();
TRAP_IF_NOT(index.value() < configuration.frame().module().functions().size());