summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/table-utils.h52
-rw-r--r--src/passes/Directize.cpp28
-rw-r--r--src/wasm2js.h76
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() {