diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/table-utils.h | 52 | ||||
-rw-r--r-- | src/passes/Directize.cpp | 28 | ||||
-rw-r--r-- | src/wasm2js.h | 76 |
3 files changed, 93 insertions, 63 deletions
diff --git a/src/ir/table-utils.h b/src/ir/table-utils.h new file mode 100644 index 000000000..4b3b7005c --- /dev/null +++ b/src/ir/table-utils.h @@ -0,0 +1,52 @@ +/* + * Copyright 2019 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef wasm_ir_table_h +#define wasm_ir_table_h + +#include "wasm.h" +#include "wasm-traversal.h" + +namespace wasm { + +struct FlatTable { + std::vector<Name> names; + bool valid; + + FlatTable(Table& table) { + valid = true; + for (auto& segment : table.segments) { + auto offset = segment.offset; + if (!offset->is<Const>()) { + // TODO: handle some non-constant segments + valid = false; + return; + } + Index start = offset->cast<Const>()->value.geti32(); + Index end = start + segment.data.size(); + if (end > names.size()) { + names.resize(end); + } + for (Index i = 0; i < segment.data.size(); i++) { + names[start + i] = segment.data[i]; + } + } + } +}; + +} // namespace wasm + +#endif // wasm_ir_table_h diff --git a/src/passes/Directize.cpp b/src/passes/Directize.cpp index 8d5cacdaf..3d8fcdfdd 100644 --- a/src/passes/Directize.cpp +++ b/src/passes/Directize.cpp @@ -27,37 +27,13 @@ #include "wasm-builder.h" #include "wasm-traversal.h" #include "asm_v_wasm.h" -#include <ir/utils.h> +#include "ir/table-utils.h" +#include "ir/utils.h" namespace wasm { namespace { -struct FlatTable { - std::vector<Name> names; - bool valid; - - FlatTable(Table& table) { - valid = true; - for (auto& segment : table.segments) { - auto offset = segment.offset; - if (!offset->is<Const>()) { - // TODO: handle some non-constant segments - valid = false; - return; - } - Index start = offset->cast<Const>()->value.geti32(); - Index end = start + segment.data.size(); - if (end > names.size()) { - names.resize(end); - } - for (Index i = 0; i < segment.data.size(); i++) { - names[start + i] = segment.data[i]; - } - } - } -}; - struct FunctionDirectizer : public WalkerPass<PostWalker<FunctionDirectizer>> { bool isFunctionParallel() override { return true; } diff --git a/src/wasm2js.h b/src/wasm2js.h index fab39267d..50968046f 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -38,6 +38,7 @@ #include "ir/load-utils.h" #include "ir/module-utils.h" #include "ir/names.h" +#include "ir/table-utils.h" #include "ir/utils.h" #include "passes/passes.h" #include "support/base64.h" @@ -267,7 +268,6 @@ private: std::unordered_map<const char*, IString> mangledNames[(int) NameScope::Max]; std::unordered_set<IString> allMangledNames; - // All our function tables have the same size TODO: optimize? size_t tableSize; bool almostASM = false; @@ -275,7 +275,7 @@ private: void addBasics(Ref ast); void addFunctionImport(Ref ast, Function* import); void addGlobalImport(Ref ast, Global* import); - void addTables(Ref ast, Module* wasm); + void addTable(Ref ast, Module* wasm); void addExports(Ref ast, Module* wasm); void addGlobal(Ref ast, Global* global); void setNeedsAlmostASM(const char *reason); @@ -387,7 +387,7 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) { asmFunc[3]->push_back(ValueBuilder::makeName("// EMSCRIPTEN_END_FUNCS")); } - addTables(asmFunc[3], wasm); + addTable(asmFunc[3], wasm); // memory XXX addExports(asmFunc[3], wasm); return ret; @@ -499,38 +499,43 @@ void Wasm2JSBuilder::addGlobalImport(Ref ast, Global* import) { ); } -void Wasm2JSBuilder::addTables(Ref ast, Module* wasm) { - std::map<std::string, std::vector<IString>> tables; // asm.js tables, sig => contents of table - for (Table::Segment& seg : wasm->table.segments) { - for (size_t i = 0; i < seg.data.size(); i++) { - Name name = seg.data[i]; - auto func = wasm->getFunction(name); - std::string sig = getSig(func); - auto& table = tables[sig]; - if (table.size() == 0) { - // fill it with the first of its type seen. we have to fill with something; and for asm2wasm output, the first is the null anyhow - table.resize(tableSize); - for (size_t j = 0; j < tableSize; j++) { - table[j] = fromName(name, NameScope::Top); - } - } else { - table[i + constOffset(seg)] = fromName(name, NameScope::Top); - } - } - } - for (auto& pair : tables) { - auto& sig = pair.first; - auto& table = pair.second; - std::string stable = std::string("FUNCTION_TABLE_") + sig; - IString asmName = IString(stable.c_str(), false); - // add to asm module +void Wasm2JSBuilder::addTable(Ref ast, Module* wasm) { + // Emit a simple flat table as a JS array literal. Otherwise, + // emit assignments separately for each index. + FlatTable flat(wasm->table); + assert(flat.valid); // TODO: non-flat tables + if (!wasm->table.imported()) { Ref theVar = ValueBuilder::makeVar(); ast->push_back(theVar); Ref theArray = ValueBuilder::makeArray(); - ValueBuilder::appendToVar(theVar, asmName, theArray); - for (auto& name : table) { + ValueBuilder::appendToVar(theVar, FUNCTION_TABLE, theArray); + Name null("null"); + for (auto& name : flat.names) { + if (name.is()) { + name = fromName(name, NameScope::Top); + } else { + name = null; + } ValueBuilder::appendToArray(theArray, ValueBuilder::makeName(name)); } + } else { + // TODO: optimize for size + for (auto& segment : wasm->table.segments) { + auto offset = segment.offset; + Index start = offset->cast<Const>()->value.geti32(); + for (Index i = 0; i < segment.data.size(); i++) { + ast->push_back(ValueBuilder::makeStatement( + ValueBuilder::makeBinary( + ValueBuilder::makeSub( + ValueBuilder::makeName(FUNCTION_TABLE), + ValueBuilder::makeInt(start + i) + ), + SET, + ValueBuilder::makeName(fromName(segment.data[i], NameScope::Top)) + ) + )); + } + } } } @@ -1058,11 +1063,8 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, IString resul Ref visitCallIndirect(CallIndirect* curr) { // TODO: the codegen here is a pessimization of what the ideal codegen // looks like. Eventually if necessary this should be tightened up in the - // case that the argument expression don't have any side effects. + // case that the argument expression doesn't have any side effects. assert(isStatement(curr)); - std::string stable = std::string("FUNCTION_TABLE_") + - getSig(module->getFunctionType(curr->fullType)); - IString table = IString(stable.c_str(), false); Ref ret = ValueBuilder::makeBlock(); ScopedTemp idx(i32, parent, func); return makeStatementizedCall( @@ -1071,8 +1073,8 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, IString resul [&]() { flattenAppend(ret, visitAndAssign(curr->target, idx)); return ValueBuilder::makeCall(ValueBuilder::makeSub( - ValueBuilder::makeName(table), - ValueBuilder::makeBinary(idx.getAstName(), AND, ValueBuilder::makeInt(parent->getTableSize()-1)) + ValueBuilder::makeName(FUNCTION_TABLE), + idx.getAstName() )); }, result, @@ -2031,7 +2033,7 @@ void Wasm2JSGlue::emitPre() { } void Wasm2JSGlue::emitPreEmscripten() { - out << "function instantiate(asmLibraryArg, wasmMemory, wasmTable) {\n\n"; + out << "function instantiate(asmLibraryArg, wasmMemory, FUNCTION_TABLE) {\n\n"; } void Wasm2JSGlue::emitPreES6() { |