diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/table-utils.h | 15 | ||||
-rw-r--r-- | src/wasm.h | 2 | ||||
-rw-r--r-- | src/wasm/wasm-emscripten.cpp | 79 |
3 files changed, 55 insertions, 41 deletions
diff --git a/src/ir/table-utils.h b/src/ir/table-utils.h index e0453dece..da0bb7241 100644 --- a/src/ir/table-utils.h +++ b/src/ir/table-utils.h @@ -50,16 +50,9 @@ struct FlatTable { } }; -// Ensure one table segment exists. This adds the table if necessary, then -// adds a segment if we need one. -inline Table::Segment& ensureTableWithOneSegment(Table& table, Module& wasm) { - table.exists = true; - if (table.segments.size() == 0) { - table.segments.resize(1); - table.segments[0].offset = LiteralUtils::makeZero(Type::i32, wasm); - } +inline Table::Segment& getSingletonSegment(Table& table, Module& wasm) { if (table.segments.size() != 1) { - Fatal() << "can't ensure 1 segment"; + Fatal() << "Table doesn't have a singleton segment."; } return table.segments[0]; } @@ -72,7 +65,7 @@ inline Table::Segment& ensureTableWithOneSegment(Table& table, Module& wasm) { // module has a single table segment, and that the dylink section indicates // we can validly append to that segment, see the check below. inline Index append(Table& table, Name name, Module& wasm) { - auto& segment = ensureTableWithOneSegment(table, wasm); + auto& segment = getSingletonSegment(table, wasm); auto tableIndex = segment.data.size(); if (wasm.dylinkSection) { if (segment.data.size() != wasm.dylinkSection->tableSize) { @@ -92,7 +85,7 @@ inline Index append(Table& table, Name name, Module& wasm) { // Checks if a function is already in the table. Returns that index if so, // otherwise appends it. inline Index getOrAppend(Table& table, Name name, Module& wasm) { - auto& segment = ensureTableWithOneSegment(table, wasm); + auto& segment = getSingletonSegment(table, wasm); for (Index i = 0; i < segment.data.size(); i++) { if (segment.data[i] == name) { return i; diff --git a/src/wasm.h b/src/wasm.h index 73f22e7d7..f0d8f13ba 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1437,7 +1437,7 @@ class Global : public Importable { public: Name name; Type type; - Expression* init; + Expression* init = nullptr; bool mutable_ = false; }; diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp index 5c411b454..0d71e8f00 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -22,7 +22,6 @@ #include "asmjs/shared-constants.h" #include "ir/import-utils.h" #include "ir/literal-utils.h" -#include "ir/manipulation.h" #include "ir/module-utils.h" #include "ir/table-utils.h" #include "shared-constants.h" @@ -217,6 +216,7 @@ void EmscriptenGlueGenerator::generateRuntimeFunctions() { static Function* ensureFunctionImport(Module* module, Name name, Signature sig) { // See if its already imported. + // FIXME: O(N) ImportInfo info(*module); if (auto* f = info.getImportedFunction(ENV, name)) { return f; @@ -231,6 +231,23 @@ ensureFunctionImport(Module* module, Name name, Signature sig) { return import; } +static Global* ensureGlobalImport(Module* module, Name name, Type type) { + // See if its already imported. + // FIXME: O(N) + ImportInfo info(*module); + if (auto* g = info.getImportedGlobal(ENV, name)) { + return g; + } + // Failing that create a new import. + auto import = new Global; + import->name = name; + import->module = ENV; + import->base = name; + import->type = type; + module->addGlobal(import); + return import; +} + // Convert LLVM PIC ABI to emscripten ABI // // When generating -fPIC code llvm will generate imports call GOT.mem and @@ -281,43 +298,47 @@ Function* EmscriptenGlueGenerator::generateAssignGOTEntriesFunction() { ImportInfo importInfo(wasm); + // We may have to add things to the table. + Global* tableBase = nullptr; + for (Global* g : gotFuncEntries) { - Function* f = nullptr; // The function has to exist either as export or an import. // Note that we don't search for the function by name since its internal // name may be different. auto* ex = wasm.getExportOrNull(g->base); if (ex) { assert(ex->kind == ExternalKind::Function); - f = wasm.getFunction(ex->value); - if (!sideModule) { - // This is exported, so must be one of the functions implemented here. - // Simply add it to the table, and use that index. The loader will - // know to reuse that index for other modules so they all share the - // same index and function pointer equality works. - // We may be able to do something for side modules as well, however, - // that would require at least updating the dylink section. - if (f->imported()) { - Fatal() << "GOT.func entry is both imported and exported: " - << g->base; - } - auto tableIndex = TableUtils::getOrAppend(wasm.table, f->name, wasm); - auto* c = LiteralUtils::makeFromInt32(tableIndex, Type::i32, wasm); - // The base relative to which we are computed is the offset of the - // singleton segment. - auto* getBase = - ExpressionManipulator::copy(wasm.table.segments[0].offset, wasm); - auto* add = builder.makeBinary(AddInt32, getBase, c); - auto* globalSet = builder.makeGlobalSet(g->name, add); - block->list.push_back(globalSet); - continue; + auto* f = wasm.getFunction(ex->value); + // This is exported, so must be one of the functions implemented here. + // Simply add it to the table, and use that index. The loader will + // know to reuse that index for other modules so they all share the + // same index and function pointer equality works. + if (f->imported()) { + Fatal() << "GOT.func entry is both imported and exported: " << g->base; } - // Otherwise, this is a side module, and fall through to join the case - // of an import. - } else { - // This is imported. Create an fp$ import to get the function table index. - f = importInfo.getImportedFunction(ENV, g->base); + // The base relative to which we are computed is the offset of the + // singleton segment, which we must ensure exists + if (!tableBase) { + tableBase = ensureGlobalImport(&wasm, TABLE_BASE, Type::i32); + } + if (!wasm.table.exists) { + wasm.table.exists = true; + } + if (wasm.table.segments.empty()) { + wasm.table.segments.resize(1); + wasm.table.segments[0].offset = + builder.makeGlobalGet(tableBase->name, Type::i32); + } + auto tableIndex = TableUtils::getOrAppend(wasm.table, f->name, wasm); + auto* c = LiteralUtils::makeFromInt32(tableIndex, Type::i32, wasm); + auto* getBase = builder.makeGlobalGet(tableBase->name, Type::i32); + auto* add = builder.makeBinary(AddInt32, getBase, c); + auto* globalSet = builder.makeGlobalSet(g->name, add); + block->list.push_back(globalSet); + continue; } + // This is imported. Create an fp$ import to get the function table index. + auto* f = importInfo.getImportedFunction(ENV, g->base); if (!f) { Fatal() << "GOT.func entry with no import/export: " << g->base; } |