summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/abi/js.h13
-rw-r--r--src/asmjs/shared-constants.cpp4
-rw-r--r--src/asmjs/shared-constants.h1
-rw-r--r--src/wasm2js.h73
4 files changed, 74 insertions, 17 deletions
diff --git a/src/abi/js.h b/src/abi/js.h
index e121e9b28..b8f56f14d 100644
--- a/src/abi/js.h
+++ b/src/abi/js.h
@@ -36,6 +36,9 @@ extern IString SCRATCH_STORE_F64;
extern IString MEMORY_INIT;
extern IString MEMORY_FILL;
extern IString MEMORY_COPY;
+extern IString TABLE_GROW;
+extern IString TABLE_FILL;
+extern IString TABLE_COPY;
extern IString DATA_DROP;
extern IString ATOMIC_WAIT_I32;
extern IString ATOMIC_RMW_I64;
@@ -81,6 +84,13 @@ inline void ensureHelpers(Module* wasm, IString specific = IString()) {
Type::i32);
ensureImport(GET_STASHED_BITS, {}, Type::i32);
ensureImport(TRAP, {}, Type::none);
+
+ if (wasm->features.hasReferenceTypes()) {
+ auto funcref = Type(HeapType::func, Nullable);
+ ensureImport(TABLE_GROW, {funcref, Type::i32}, Type::none);
+ ensureImport(TABLE_FILL, {Type::i32, funcref, Type::i32}, Type::none);
+ ensureImport(TABLE_COPY, {Type::i32, Type::i32, Type::i32}, Type::none);
+ }
}
inline bool isHelper(IString name) {
@@ -88,7 +98,8 @@ inline bool isHelper(IString name) {
name == SCRATCH_LOAD_F32 || name == SCRATCH_STORE_F32 ||
name == SCRATCH_LOAD_F64 || name == SCRATCH_STORE_F64 ||
name == ATOMIC_WAIT_I32 || name == MEMORY_INIT ||
- name == MEMORY_FILL || name == MEMORY_COPY || name == DATA_DROP ||
+ name == MEMORY_FILL || name == MEMORY_COPY || name == TABLE_GROW ||
+ name == TABLE_FILL || name == TABLE_COPY || name == DATA_DROP ||
name == ATOMIC_RMW_I64 || name == GET_STASHED_BITS || name == TRAP;
}
diff --git a/src/asmjs/shared-constants.cpp b/src/asmjs/shared-constants.cpp
index 57b9c4f87..bd924f179 100644
--- a/src/asmjs/shared-constants.cpp
+++ b/src/asmjs/shared-constants.cpp
@@ -62,6 +62,7 @@ IString ENV("env");
IString STACKTOP("STACKTOP");
IString STACK_MAX("STACK_MAX");
IString INSTRUMENT("instrument");
+IString LENGTH("length");
IString MATH_IMUL("Math_imul");
IString MATH_ABS("Math_abs");
IString MATH_CEIL("Math_ceil");
@@ -111,6 +112,9 @@ IString SCRATCH_STORE_F64("wasm2js_scratch_store_f64");
IString MEMORY_INIT("wasm2js_memory_init");
IString MEMORY_FILL("wasm2js_memory_fill");
IString MEMORY_COPY("wasm2js_memory_copy");
+IString TABLE_GROW("wasm2js_table_grow");
+IString TABLE_FILL("wasm2js_table_fill");
+IString TABLE_COPY("wasm2js_table_copy");
IString DATA_DROP("wasm2js_data_drop");
IString ATOMIC_WAIT_I32("wasm2js_atomic_wait_i32");
IString ATOMIC_RMW_I64("wasm2js_atomic_rmw_i64");
diff --git a/src/asmjs/shared-constants.h b/src/asmjs/shared-constants.h
index e199b1361..d48da560e 100644
--- a/src/asmjs/shared-constants.h
+++ b/src/asmjs/shared-constants.h
@@ -65,6 +65,7 @@ extern IString ENV;
extern IString STACKTOP;
extern IString STACK_MAX;
extern IString INSTRUMENT;
+extern IString LENGTH;
extern IString MATH_IMUL;
extern IString MATH_ABS;
extern IString MATH_CLZ32;
diff --git a/src/wasm2js.h b/src/wasm2js.h
index 2084c0453..dd4e61a51 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -672,12 +672,11 @@ void Wasm2JSBuilder::addTable(Ref ast, Module* wasm) {
if (!table->imported()) {
TableUtils::FlatTable flat(*wasm, *table);
if (flat.valid) {
- Name null("null");
for (auto& name : flat.names) {
if (name.is()) {
name = fromName(name, NameScope::Top);
} else {
- name = null;
+ name = NULL_;
}
ValueBuilder::appendToArray(theArray, ValueBuilder::makeName(name));
}
@@ -2221,11 +2220,11 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
visit(curr->value, EXPRESSION_RESULT),
visit(curr->size, EXPRESSION_RESULT));
}
- Ref visitRefNull(RefNull* curr) { return ValueBuilder::makeName("null"); }
+ Ref visitRefNull(RefNull* curr) { return ValueBuilder::makeName(NULL_); }
Ref visitRefIsNull(RefIsNull* curr) {
return ValueBuilder::makeBinary(visit(curr->value, EXPRESSION_RESULT),
EQ,
- ValueBuilder::makeName("null"));
+ ValueBuilder::makeName(NULL_));
}
Ref visitRefFunc(RefFunc* curr) {
return ValueBuilder::makeName(fromName(curr->func, NameScope::Top));
@@ -2236,28 +2235,40 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
visit(curr->right, EXPRESSION_RESULT));
}
Ref visitTableGet(TableGet* curr) {
- unimplemented(curr);
- WASM_UNREACHABLE("unimp");
+ return ValueBuilder::makeSub(ValueBuilder::makeName(FUNCTION_TABLE),
+ visit(curr->index, EXPRESSION_RESULT));
}
Ref visitTableSet(TableSet* curr) {
- unimplemented(curr);
- WASM_UNREACHABLE("unimp");
+ auto sub = ValueBuilder::makeSub(ValueBuilder::makeName(FUNCTION_TABLE),
+ visit(curr->index, EXPRESSION_RESULT));
+ auto value = visit(curr->value, EXPRESSION_RESULT);
+ return ValueBuilder::makeBinary(sub, SET, value);
}
Ref visitTableSize(TableSize* curr) {
- unimplemented(curr);
- WASM_UNREACHABLE("unimp");
+ return ValueBuilder::makeDot(ValueBuilder::makeName(FUNCTION_TABLE),
+ ValueBuilder::makeName(LENGTH));
}
Ref visitTableGrow(TableGrow* curr) {
- unimplemented(curr);
- WASM_UNREACHABLE("unimp");
+ ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::TABLE_GROW);
+ // Also ensure fill, as grow calls fill internally.
+ ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::TABLE_FILL);
+ return ValueBuilder::makeCall(ABI::wasm2js::TABLE_GROW,
+ visit(curr->value, EXPRESSION_RESULT),
+ visit(curr->delta, EXPRESSION_RESULT));
}
Ref visitTableFill(TableFill* curr) {
- unimplemented(curr);
- WASM_UNREACHABLE("unimp");
+ ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::TABLE_FILL);
+ return ValueBuilder::makeCall(ABI::wasm2js::TABLE_FILL,
+ visit(curr->dest, EXPRESSION_RESULT),
+ visit(curr->value, EXPRESSION_RESULT),
+ visit(curr->size, EXPRESSION_RESULT));
}
Ref visitTableCopy(TableCopy* curr) {
- unimplemented(curr);
- WASM_UNREACHABLE("unimp");
+ ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::TABLE_COPY);
+ return ValueBuilder::makeCall(ABI::wasm2js::TABLE_COPY,
+ visit(curr->dest, EXPRESSION_RESULT),
+ visit(curr->source, EXPRESSION_RESULT),
+ visit(curr->size, EXPRESSION_RESULT));
}
Ref visitTry(Try* curr) {
unimplemented(curr);
@@ -3026,6 +3037,36 @@ void Wasm2JSGlue::emitSpecialSupport() {
bufferView.copyWithin(dest, source, source + size);
}
)";
+ } else if (import->base == ABI::wasm2js::TABLE_GROW) {
+ out << R"(
+ function wasm2js_table_grow(value, delta) {
+ // TODO: traps on invalid things
+ var oldSize = FUNCTION_TABLE.length;
+ FUNCTION_TABLE.length = oldSize + delta;
+ if (newSize > oldSize) {
+ __wasm_table_fill(oldSize, value, delta)
+ }
+ return oldSize;
+ }
+ )";
+ } else if (import->base == ABI::wasm2js::TABLE_FILL) {
+ out << R"(
+ function __wasm_table_fill(dest, value, size) {
+ // TODO: traps on invalid things
+ for (var i = 0; i < size; i++) {
+ FUNCTION_TABLE[dest + i] = value;
+ }
+ }
+ )";
+ } else if (import->base == ABI::wasm2js::TABLE_COPY) {
+ out << R"(
+ function __wasm_table_copy(dest, source, size) {
+ // TODO: traps on invalid things
+ for (var i = 0; i < size; i++) {
+ FUNCTION_TABLE[dest + i] = FUNCTION_TABLE[source + i];
+ }
+ }
+ )";
} else if (import->base == ABI::wasm2js::DATA_DROP) {
out << R"(
function wasm2js_data_drop(segment) {