summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/table-utils.h15
-rw-r--r--src/wasm.h2
-rw-r--r--src/wasm/wasm-emscripten.cpp79
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;
}