diff options
-rw-r--r-- | src/ir/table-utils.h | 43 | ||||
-rw-r--r-- | src/passes/Directize.cpp | 6 | ||||
-rw-r--r-- | src/passes/PostEmscripten.cpp | 7 | ||||
-rw-r--r-- | src/tools/wasm-emscripten-finalize.cpp | 13 | ||||
-rw-r--r-- | src/wasm-emscripten.h | 2 | ||||
-rw-r--r-- | src/wasm/wasm-emscripten.cpp | 49 | ||||
-rw-r--r-- | src/wasm2js.h | 2 | ||||
-rw-r--r-- | test/lld/main_module_table.wat | 9 | ||||
-rw-r--r-- | test/lld/main_module_table.wat.out | 106 | ||||
-rw-r--r-- | test/lld/main_module_table_2.wat | 10 | ||||
-rw-r--r-- | test/lld/main_module_table_2.wat.out | 106 | ||||
-rw-r--r-- | test/lld/main_module_table_3.wat | 11 | ||||
-rw-r--r-- | test/lld/main_module_table_3.wat.out | 106 | ||||
-rw-r--r-- | test/lld/main_module_table_4.wat | 12 | ||||
-rw-r--r-- | test/lld/main_module_table_4.wat.out | 108 | ||||
-rw-r--r-- | test/lld/main_module_table_5.wat | 16 | ||||
-rw-r--r-- | test/lld/main_module_table_5.wat.out | 114 |
17 files changed, 696 insertions, 24 deletions
diff --git a/src/ir/table-utils.h b/src/ir/table-utils.h index d2dc3a7d5..3c49ab16a 100644 --- a/src/ir/table-utils.h +++ b/src/ir/table-utils.h @@ -17,11 +17,14 @@ #ifndef wasm_ir_table_h #define wasm_ir_table_h +#include "ir/literal-utils.h" #include "wasm-traversal.h" #include "wasm.h" namespace wasm { +namespace TableUtils { + struct FlatTable { std::vector<Name> names; bool valid; @@ -47,6 +50,46 @@ 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); + } + if (table.segments.size() != 1) { + Fatal() << "can't ensure 1 segment"; + } + return table.segments[0]; +} + +// Appends a name to the table. This assumes the table has 0 or 1 segments, +// as with 2 or more it's ambiguous what we should do (use a hole in the middle +// or not). +inline Index append(Table& table, Name name, Module& wasm) { + auto& segment = ensureTableWithOneSegment(table, wasm); + table.segments[0]; + auto tableIndex = segment.data.size(); + segment.data.push_back(name); + table.initial = table.initial + 1; + return tableIndex; +} + +// 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); + for (Index i = 0; i < segment.data.size(); i++) { + if (segment.data[i] == name) { + return i; + } + } + return append(table, name, wasm); +} + +} // namespace TableUtils + } // namespace wasm #endif // wasm_ir_table_h diff --git a/src/passes/Directize.cpp b/src/passes/Directize.cpp index 52aa7e087..037eca0da 100644 --- a/src/passes/Directize.cpp +++ b/src/passes/Directize.cpp @@ -39,7 +39,7 @@ struct FunctionDirectizer : public WalkerPass<PostWalker<FunctionDirectizer>> { Pass* create() override { return new FunctionDirectizer(flatTable); } - FunctionDirectizer(FlatTable* flatTable) : flatTable(flatTable) {} + FunctionDirectizer(TableUtils::FlatTable* flatTable) : flatTable(flatTable) {} void visitCallIndirect(CallIndirect* curr) { if (auto* c = curr->target->dynCast<Const>()) { @@ -77,7 +77,7 @@ struct FunctionDirectizer : public WalkerPass<PostWalker<FunctionDirectizer>> { } private: - FlatTable* flatTable; + TableUtils::FlatTable* flatTable; bool changedTypes = false; void replaceWithUnreachable(CallIndirect* call) { @@ -104,7 +104,7 @@ struct Directize : public Pass { return; } } - FlatTable flatTable(module->table); + TableUtils::FlatTable flatTable(module->table); if (!flatTable.valid) { return; } diff --git a/src/passes/PostEmscripten.cpp b/src/passes/PostEmscripten.cpp index ccf985c50..8efaae8c5 100644 --- a/src/passes/PostEmscripten.cpp +++ b/src/passes/PostEmscripten.cpp @@ -135,7 +135,7 @@ struct PostEmscripten : public Pass { // Next, see if the Table is flat, which we need in order to see where // invokes go statically. (In dynamic linking, the table is not flat, // and we can't do this.) - FlatTable flatTable(module->table); + TableUtils::FlatTable flatTable(module->table); if (!flatTable.valid) { return; } @@ -167,9 +167,10 @@ struct PostEmscripten : public Pass { Pass* create() override { return new OptimizeInvokes(map, flatTable); } std::map<Function*, Info>& map; - FlatTable& flatTable; + TableUtils::FlatTable& flatTable; - OptimizeInvokes(std::map<Function*, Info>& map, FlatTable& flatTable) + OptimizeInvokes(std::map<Function*, Info>& map, + TableUtils::FlatTable& flatTable) : map(map), flatTable(flatTable) {} void visitCall(Call* curr) { diff --git a/src/tools/wasm-emscripten-finalize.cpp b/src/tools/wasm-emscripten-finalize.cpp index 9ade001ef..576b64a1a 100644 --- a/src/tools/wasm-emscripten-finalize.cpp +++ b/src/tools/wasm-emscripten-finalize.cpp @@ -50,7 +50,7 @@ int main(int argc, const char* argv[]) { bool emitBinary = true; bool debugInfo = false; bool DWARF = false; - bool isSideModule = false; + bool sideModule = false; bool legalizeJavaScriptFFI = true; bool checkStackOverflow = false; uint64_t globalBase = INVALID_BASE; @@ -100,8 +100,8 @@ int main(int argc, const char* argv[]) { "", "Input is an emscripten side module", Options::Arguments::Zero, - [&isSideModule](Options* o, const std::string& argument) { - isSideModule = true; + [&sideModule](Options* o, const std::string& argument) { + sideModule = true; }) .add("--input-source-map", "-ism", @@ -191,7 +191,7 @@ int main(int argc, const char* argv[]) { uint32_t dataSize = 0; - if (!isSideModule) { + if (!sideModule) { if (globalBase == INVALID_BASE) { Fatal() << "globalBase must be set"; } @@ -215,6 +215,7 @@ int main(int argc, const char* argv[]) { EmscriptenGlueGenerator generator(wasm); generator.setStandalone(standaloneWasm); + generator.setSideModule(sideModule); generator.fixInvokeFunctionNames(); @@ -232,11 +233,11 @@ int main(int argc, const char* argv[]) { } wasm.updateMaps(); - if (checkStackOverflow && !isSideModule) { + if (checkStackOverflow && !sideModule) { generator.enforceStackLimit(); } - if (isSideModule) { + if (sideModule) { BYN_TRACE("finalizing as side module\n"); generator.replaceStackPointerGlobal(); generator.generatePostInstantiateFunction(); diff --git a/src/wasm-emscripten.h b/src/wasm-emscripten.h index c7689b4bc..80277cb18 100644 --- a/src/wasm-emscripten.h +++ b/src/wasm-emscripten.h @@ -32,6 +32,7 @@ public: useStackPointerGlobal(stackPointerOffset == 0) {} void setStandalone(bool standalone_) { standalone = standalone_; } + void setSideModule(bool sideModule_) { sideModule = sideModule_; } void generateRuntimeFunctions(); Function* generateMemoryGrowthFunction(); @@ -72,6 +73,7 @@ private: Address stackPointerOffset; bool useStackPointerGlobal; bool standalone; + bool sideModule; // Used by generateDynCallThunk to track all the dynCall functions created // so far. std::unordered_set<Signature> sigs; diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp index 8357983b2..5c411b454 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -22,7 +22,9 @@ #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" #include "support/debug.h" #include "wasm-builder.h" @@ -214,12 +216,12 @@ void EmscriptenGlueGenerator::generateRuntimeFunctions() { static Function* ensureFunctionImport(Module* module, Name name, Signature sig) { - // Then see if its already imported + // See if its already imported. ImportInfo info(*module); - if (Function* f = info.getImportedFunction(ENV, name)) { + if (auto* f = info.getImportedFunction(ENV, name)) { return f; } - // Failing that create a new function import. + // Failing that create a new import. auto import = new Function; import->name = name; import->module = ENV; @@ -277,6 +279,8 @@ Function* EmscriptenGlueGenerator::generateAssignGOTEntriesFunction() { block->list.push_back(globalSet); } + ImportInfo importInfo(wasm); + for (Global* g : gotFuncEntries) { Function* f = nullptr; // The function has to exist either as export or an import. @@ -286,20 +290,43 @@ Function* EmscriptenGlueGenerator::generateAssignGOTEntriesFunction() { if (ex) { assert(ex->kind == ExternalKind::Function); f = wasm.getFunction(ex->value); - } else { - ImportInfo info(wasm); - f = info.getImportedFunction(ENV, g->base); - if (!f) { - Fatal() << "GOT.func entry with no import/export: " << g->base; + 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; } + // 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); + } + if (!f) { + Fatal() << "GOT.func entry with no import/export: " << g->base; } - Name getter( (std::string("fp$") + g->base.c_str() + std::string("$") + getSig(f)) .c_str()); ensureFunctionImport(&wasm, getter, Signature(Type::none, Type::i32)); - Expression* call = builder.makeCall(getter, {}, Type::i32); - GlobalSet* globalSet = builder.makeGlobalSet(g->name, call); + auto* call = builder.makeCall(getter, {}, Type::i32); + auto* globalSet = builder.makeGlobalSet(g->name, call); block->list.push_back(globalSet); } diff --git a/src/wasm2js.h b/src/wasm2js.h index cdc109cfa..cc2cfa128 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -530,7 +530,7 @@ void Wasm2JSBuilder::addGlobalImport(Ref ast, Global* import) { 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); + TableUtils::FlatTable flat(wasm->table); if (flat.valid && !wasm->table.imported()) { Ref theVar = ValueBuilder::makeVar(); ast->push_back(theVar); diff --git a/test/lld/main_module_table.wat b/test/lld/main_module_table.wat new file mode 100644 index 000000000..b63b4d8fe --- /dev/null +++ b/test/lld/main_module_table.wat @@ -0,0 +1,9 @@ +(module + (import "env" "__stack_pointer" (global $sp (mut i32))) + (import "GOT.func" "__stdio_write" (global $gimport$9 (mut i32))) + (global $global i32 (i32.const 42)) + (export "__stdio_write" (func $__stdio_write)) + (export "__data_end" (global $global)) + (func $__stdio_write + ) +) diff --git a/test/lld/main_module_table.wat.out b/test/lld/main_module_table.wat.out new file mode 100644 index 000000000..fd292809f --- /dev/null +++ b/test/lld/main_module_table.wat.out @@ -0,0 +1,106 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "__stack_pointer" (global $sp_import i32)) + (table $0 1 funcref) + (elem (i32.const 0) $__stdio_write) + (global $gimport$9 (mut i32) (i32.const 0)) + (global $global i32 (i32.const 42)) + (global $sp (mut i32) (global.get $sp_import)) + (export "__stdio_write" (func $__stdio_write)) + (export "__data_end" (global $global)) + (export "stackSave" (func $stackSave)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackRestore" (func $stackRestore)) + (export "__growWasmMemory" (func $__growWasmMemory)) + (export "__assign_got_enties" (func $__assign_got_enties)) + (export "dynCall_v" (func $dynCall_v)) + (func $__stdio_write (; 0 ;) + (nop) + ) + (func $stackSave (; 1 ;) (result i32) + (global.get $sp) + ) + (func $stackAlloc (; 2 ;) (param $0 i32) (result i32) + (local $1 i32) + (global.set $sp + (local.tee $1 + (i32.and + (i32.sub + (global.get $sp) + (local.get $0) + ) + (i32.const -16) + ) + ) + ) + (local.get $1) + ) + (func $stackRestore (; 3 ;) (param $0 i32) + (global.set $sp + (local.get $0) + ) + ) + (func $__growWasmMemory (; 4 ;) (param $newSize i32) (result i32) + (memory.grow + (local.get $newSize) + ) + ) + (func $__assign_got_enties (; 5 ;) + (global.set $gimport$9 + (i32.add + (i32.const 0) + (i32.const 0) + ) + ) + ) + (func $dynCall_v (; 6 ;) (param $fptr i32) + (call_indirect (type $none_=>_none) + (local.get $fptr) + ) + ) +) +(; +--BEGIN METADATA -- +{ + "staticBump": 4294966770, + "tableSize": 1, + "initializers": [ + "__assign_got_enties" + ], + "declares": [ + ], + "externs": [ + "___stack_pointer" + ], + "implementedFunctions": [ + "___stdio_write", + "_stackSave", + "_stackAlloc", + "_stackRestore", + "___growWasmMemory", + "___assign_got_enties", + "_dynCall_v" + ], + "exports": [ + "__stdio_write", + "stackSave", + "stackAlloc", + "stackRestore", + "__growWasmMemory", + "__assign_got_enties", + "dynCall_v" + ], + "namedGlobals": { + "__data_end" : "42" + }, + "invokeFuncs": [ + ], + "features": [ + ], + "mainReadsParams": 0 +} +-- END METADATA -- +;) diff --git a/test/lld/main_module_table_2.wat b/test/lld/main_module_table_2.wat new file mode 100644 index 000000000..2ccc1fbcc --- /dev/null +++ b/test/lld/main_module_table_2.wat @@ -0,0 +1,10 @@ +(module + (import "env" "__stack_pointer" (global $sp (mut i32))) + (import "GOT.func" "__stdio_write" (global $gimport$9 (mut i32))) + (import "env" "table" (table $timport$9 1 funcref)) + (global $global i32 (i32.const 42)) + (export "__stdio_write" (func $__stdio_write)) + (export "__data_end" (global $global)) + (func $__stdio_write + ) +) diff --git a/test/lld/main_module_table_2.wat.out b/test/lld/main_module_table_2.wat.out new file mode 100644 index 000000000..92a40d5f2 --- /dev/null +++ b/test/lld/main_module_table_2.wat.out @@ -0,0 +1,106 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "table" (table $0 2 funcref)) + (elem (i32.const 0) $__stdio_write) + (import "env" "__stack_pointer" (global $sp_import i32)) + (global $gimport$9 (mut i32) (i32.const 0)) + (global $global i32 (i32.const 42)) + (global $sp (mut i32) (global.get $sp_import)) + (export "__stdio_write" (func $__stdio_write)) + (export "__data_end" (global $global)) + (export "stackSave" (func $stackSave)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackRestore" (func $stackRestore)) + (export "__growWasmMemory" (func $__growWasmMemory)) + (export "__assign_got_enties" (func $__assign_got_enties)) + (export "dynCall_v" (func $dynCall_v)) + (func $__stdio_write (; 0 ;) + (nop) + ) + (func $stackSave (; 1 ;) (result i32) + (global.get $sp) + ) + (func $stackAlloc (; 2 ;) (param $0 i32) (result i32) + (local $1 i32) + (global.set $sp + (local.tee $1 + (i32.and + (i32.sub + (global.get $sp) + (local.get $0) + ) + (i32.const -16) + ) + ) + ) + (local.get $1) + ) + (func $stackRestore (; 3 ;) (param $0 i32) + (global.set $sp + (local.get $0) + ) + ) + (func $__growWasmMemory (; 4 ;) (param $newSize i32) (result i32) + (memory.grow + (local.get $newSize) + ) + ) + (func $__assign_got_enties (; 5 ;) + (global.set $gimport$9 + (i32.add + (i32.const 0) + (i32.const 0) + ) + ) + ) + (func $dynCall_v (; 6 ;) (param $fptr i32) + (call_indirect (type $none_=>_none) + (local.get $fptr) + ) + ) +) +(; +--BEGIN METADATA -- +{ + "staticBump": 4294966770, + "tableSize": 2, + "initializers": [ + "__assign_got_enties" + ], + "declares": [ + ], + "externs": [ + "___stack_pointer" + ], + "implementedFunctions": [ + "___stdio_write", + "_stackSave", + "_stackAlloc", + "_stackRestore", + "___growWasmMemory", + "___assign_got_enties", + "_dynCall_v" + ], + "exports": [ + "__stdio_write", + "stackSave", + "stackAlloc", + "stackRestore", + "__growWasmMemory", + "__assign_got_enties", + "dynCall_v" + ], + "namedGlobals": { + "__data_end" : "42" + }, + "invokeFuncs": [ + ], + "features": [ + ], + "mainReadsParams": 0 +} +-- END METADATA -- +;) diff --git a/test/lld/main_module_table_3.wat b/test/lld/main_module_table_3.wat new file mode 100644 index 000000000..2f7d92ebf --- /dev/null +++ b/test/lld/main_module_table_3.wat @@ -0,0 +1,11 @@ +(module + (import "env" "__stack_pointer" (global $sp (mut i32))) + (import "GOT.func" "__stdio_write" (global $gimport$9 (mut i32))) + (import "env" "table" (table $timport$9 1 funcref)) + (elem (i32.const 0)) + (global $global i32 (i32.const 42)) + (export "__stdio_write" (func $__stdio_write)) + (export "__data_end" (global $global)) + (func $__stdio_write + ) +) diff --git a/test/lld/main_module_table_3.wat.out b/test/lld/main_module_table_3.wat.out new file mode 100644 index 000000000..92a40d5f2 --- /dev/null +++ b/test/lld/main_module_table_3.wat.out @@ -0,0 +1,106 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "table" (table $0 2 funcref)) + (elem (i32.const 0) $__stdio_write) + (import "env" "__stack_pointer" (global $sp_import i32)) + (global $gimport$9 (mut i32) (i32.const 0)) + (global $global i32 (i32.const 42)) + (global $sp (mut i32) (global.get $sp_import)) + (export "__stdio_write" (func $__stdio_write)) + (export "__data_end" (global $global)) + (export "stackSave" (func $stackSave)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackRestore" (func $stackRestore)) + (export "__growWasmMemory" (func $__growWasmMemory)) + (export "__assign_got_enties" (func $__assign_got_enties)) + (export "dynCall_v" (func $dynCall_v)) + (func $__stdio_write (; 0 ;) + (nop) + ) + (func $stackSave (; 1 ;) (result i32) + (global.get $sp) + ) + (func $stackAlloc (; 2 ;) (param $0 i32) (result i32) + (local $1 i32) + (global.set $sp + (local.tee $1 + (i32.and + (i32.sub + (global.get $sp) + (local.get $0) + ) + (i32.const -16) + ) + ) + ) + (local.get $1) + ) + (func $stackRestore (; 3 ;) (param $0 i32) + (global.set $sp + (local.get $0) + ) + ) + (func $__growWasmMemory (; 4 ;) (param $newSize i32) (result i32) + (memory.grow + (local.get $newSize) + ) + ) + (func $__assign_got_enties (; 5 ;) + (global.set $gimport$9 + (i32.add + (i32.const 0) + (i32.const 0) + ) + ) + ) + (func $dynCall_v (; 6 ;) (param $fptr i32) + (call_indirect (type $none_=>_none) + (local.get $fptr) + ) + ) +) +(; +--BEGIN METADATA -- +{ + "staticBump": 4294966770, + "tableSize": 2, + "initializers": [ + "__assign_got_enties" + ], + "declares": [ + ], + "externs": [ + "___stack_pointer" + ], + "implementedFunctions": [ + "___stdio_write", + "_stackSave", + "_stackAlloc", + "_stackRestore", + "___growWasmMemory", + "___assign_got_enties", + "_dynCall_v" + ], + "exports": [ + "__stdio_write", + "stackSave", + "stackAlloc", + "stackRestore", + "__growWasmMemory", + "__assign_got_enties", + "dynCall_v" + ], + "namedGlobals": { + "__data_end" : "42" + }, + "invokeFuncs": [ + ], + "features": [ + ], + "mainReadsParams": 0 +} +-- END METADATA -- +;) diff --git a/test/lld/main_module_table_4.wat b/test/lld/main_module_table_4.wat new file mode 100644 index 000000000..a991de4bb --- /dev/null +++ b/test/lld/main_module_table_4.wat @@ -0,0 +1,12 @@ +(module + (import "env" "__stack_pointer" (global $sp (mut i32))) + (import "GOT.func" "__stdio_write" (global $gimport$9 (mut i32))) + (import "env" "__table_base" (global $tb i32)) + (import "env" "table" (table $timport$9 1 funcref)) + (elem (global.get $tb)) + (global $global i32 (i32.const 42)) + (export "__stdio_write" (func $__stdio_write)) + (export "__data_end" (global $global)) + (func $__stdio_write + ) +) diff --git a/test/lld/main_module_table_4.wat.out b/test/lld/main_module_table_4.wat.out new file mode 100644 index 000000000..db2ef3cd8 --- /dev/null +++ b/test/lld/main_module_table_4.wat.out @@ -0,0 +1,108 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "table" (table $0 2 funcref)) + (elem (global.get $tb) $__stdio_write) + (import "env" "__stack_pointer" (global $sp_import i32)) + (import "env" "__table_base" (global $tb i32)) + (global $gimport$9 (mut i32) (i32.const 0)) + (global $global i32 (i32.const 42)) + (global $sp (mut i32) (global.get $sp_import)) + (export "__stdio_write" (func $__stdio_write)) + (export "__data_end" (global $global)) + (export "stackSave" (func $stackSave)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackRestore" (func $stackRestore)) + (export "__growWasmMemory" (func $__growWasmMemory)) + (export "__assign_got_enties" (func $__assign_got_enties)) + (export "dynCall_v" (func $dynCall_v)) + (func $__stdio_write (; 0 ;) + (nop) + ) + (func $stackSave (; 1 ;) (result i32) + (global.get $sp) + ) + (func $stackAlloc (; 2 ;) (param $0 i32) (result i32) + (local $1 i32) + (global.set $sp + (local.tee $1 + (i32.and + (i32.sub + (global.get $sp) + (local.get $0) + ) + (i32.const -16) + ) + ) + ) + (local.get $1) + ) + (func $stackRestore (; 3 ;) (param $0 i32) + (global.set $sp + (local.get $0) + ) + ) + (func $__growWasmMemory (; 4 ;) (param $newSize i32) (result i32) + (memory.grow + (local.get $newSize) + ) + ) + (func $__assign_got_enties (; 5 ;) + (global.set $gimport$9 + (i32.add + (global.get $tb) + (i32.const 0) + ) + ) + ) + (func $dynCall_v (; 6 ;) (param $fptr i32) + (call_indirect (type $none_=>_none) + (local.get $fptr) + ) + ) +) +(; +--BEGIN METADATA -- +{ + "staticBump": 4294966770, + "tableSize": 2, + "initializers": [ + "__assign_got_enties" + ], + "declares": [ + ], + "externs": [ + "___stack_pointer", + "___table_base" + ], + "implementedFunctions": [ + "___stdio_write", + "_stackSave", + "_stackAlloc", + "_stackRestore", + "___growWasmMemory", + "___assign_got_enties", + "_dynCall_v" + ], + "exports": [ + "__stdio_write", + "stackSave", + "stackAlloc", + "stackRestore", + "__growWasmMemory", + "__assign_got_enties", + "dynCall_v" + ], + "namedGlobals": { + "__data_end" : "42" + }, + "invokeFuncs": [ + ], + "features": [ + ], + "mainReadsParams": 0 +} +-- END METADATA -- +;) diff --git a/test/lld/main_module_table_5.wat b/test/lld/main_module_table_5.wat new file mode 100644 index 000000000..ee15deee5 --- /dev/null +++ b/test/lld/main_module_table_5.wat @@ -0,0 +1,16 @@ +(module + (import "env" "__stack_pointer" (global $sp (mut i32))) + (import "GOT.func" "__stdio_write" (global $gimport$9 (mut i32))) + (import "env" "__table_base" (global $tb i32)) + (import "env" "table" (table $timport$9 1 funcref)) + (elem (global.get $tb) $other $stuff) + (global $global i32 (i32.const 42)) + (export "__stdio_write" (func $__stdio_write)) + (export "__data_end" (global $global)) + (func $__stdio_write + ) + (func $other + ) + (func $stuff + ) +) diff --git a/test/lld/main_module_table_5.wat.out b/test/lld/main_module_table_5.wat.out new file mode 100644 index 000000000..590164b0f --- /dev/null +++ b/test/lld/main_module_table_5.wat.out @@ -0,0 +1,114 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "table" (table $0 2 funcref)) + (elem (global.get $tb) $other $stuff $__stdio_write) + (import "env" "__stack_pointer" (global $sp_import i32)) + (import "env" "__table_base" (global $tb i32)) + (global $gimport$9 (mut i32) (i32.const 0)) + (global $global i32 (i32.const 42)) + (global $sp (mut i32) (global.get $sp_import)) + (export "__stdio_write" (func $__stdio_write)) + (export "__data_end" (global $global)) + (export "stackSave" (func $stackSave)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackRestore" (func $stackRestore)) + (export "__growWasmMemory" (func $__growWasmMemory)) + (export "__assign_got_enties" (func $__assign_got_enties)) + (export "dynCall_v" (func $dynCall_v)) + (func $__stdio_write (; 0 ;) + (nop) + ) + (func $other (; 1 ;) + (nop) + ) + (func $stuff (; 2 ;) + (nop) + ) + (func $stackSave (; 3 ;) (result i32) + (global.get $sp) + ) + (func $stackAlloc (; 4 ;) (param $0 i32) (result i32) + (local $1 i32) + (global.set $sp + (local.tee $1 + (i32.and + (i32.sub + (global.get $sp) + (local.get $0) + ) + (i32.const -16) + ) + ) + ) + (local.get $1) + ) + (func $stackRestore (; 5 ;) (param $0 i32) + (global.set $sp + (local.get $0) + ) + ) + (func $__growWasmMemory (; 6 ;) (param $newSize i32) (result i32) + (memory.grow + (local.get $newSize) + ) + ) + (func $__assign_got_enties (; 7 ;) + (global.set $gimport$9 + (i32.add + (global.get $tb) + (i32.const 2) + ) + ) + ) + (func $dynCall_v (; 8 ;) (param $fptr i32) + (call_indirect (type $none_=>_none) + (local.get $fptr) + ) + ) +) +(; +--BEGIN METADATA -- +{ + "staticBump": 4294966770, + "tableSize": 2, + "initializers": [ + "__assign_got_enties" + ], + "declares": [ + ], + "externs": [ + "___stack_pointer", + "___table_base" + ], + "implementedFunctions": [ + "___stdio_write", + "_stackSave", + "_stackAlloc", + "_stackRestore", + "___growWasmMemory", + "___assign_got_enties", + "_dynCall_v" + ], + "exports": [ + "__stdio_write", + "stackSave", + "stackAlloc", + "stackRestore", + "__growWasmMemory", + "__assign_got_enties", + "dynCall_v" + ], + "namedGlobals": { + "__data_end" : "42" + }, + "invokeFuncs": [ + ], + "features": [ + ], + "mainReadsParams": 0 +} +-- END METADATA -- +;) |