diff options
author | Alon Zakai <azakai@google.com> | 2024-06-11 14:13:52 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-11 14:13:52 -0700 |
commit | 2dcf67049ef4d2cbcb2a65d367be97ae675f9d8a (patch) | |
tree | 6b2193693bfa44034baff985e8ccf38d3fa4af0a /src/wasm2js.h | |
parent | cdd94a01ad02e944eaa9ba5e20a1129bef9ac305 (diff) | |
download | binaryen-2dcf67049ef4d2cbcb2a65d367be97ae675f9d8a.tar.gz binaryen-2dcf67049ef4d2cbcb2a65d367be97ae675f9d8a.tar.bz2 binaryen-2dcf67049ef4d2cbcb2a65d367be97ae675f9d8a.zip |
wasm2js: Add Table operations (#6650)
TableGet, Set, Size, Grow, Fill, Copy.
Also move "null" into shared-constants, to make the code
more consistent overall.
Diffstat (limited to 'src/wasm2js.h')
-rw-r--r-- | src/wasm2js.h | 73 |
1 files changed, 57 insertions, 16 deletions
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) { |