summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm/wasm-emscripten.cpp34
-rw-r--r--test/lld/em_asm_table.wast13
-rw-r--r--test/lld/em_asm_table.wast.out64
3 files changed, 104 insertions, 7 deletions
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index a99482d39..c61e40b1d 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -376,10 +376,12 @@ struct AsmConstWalker : public PostWalker<AsmConstWalker> {
segmentOffsets(getSegmentOffsets(wasm)) { }
void visitCall(Call* curr);
+ void visitTable(Table* curr);
void process();
private:
+ std::string fixupNameWithSig(Name& name, std::string baseSig);
Literal idLiteralForCode(std::string code);
std::string asmConstSig(std::string baseSig);
Name nameForImportWithSig(std::string sig);
@@ -392,18 +394,24 @@ private:
void AsmConstWalker::visitCall(Call* curr) {
auto* import = wasm.getFunction(curr->target);
if (import->imported() && import->base.hasSubstring(EMSCRIPTEN_ASM_CONST)) {
+ auto baseSig = getSig(curr);
+ auto sig = fixupNameWithSig(curr->target, baseSig);
+
auto arg = curr->operands[0]->cast<Const>();
auto code = codeForConstAddr(wasm, segmentOffsets, arg);
arg->value = idLiteralForCode(code);
- auto baseSig = getSig(curr);
- auto sig = asmConstSig(baseSig);
sigsForCode[code].insert(sig);
- auto importName = nameForImportWithSig(sig);
- curr->target = importName;
+ }
+}
- if (allSigs.count(sig) == 0) {
- allSigs.insert(sig);
- queueImport(importName, baseSig);
+void AsmConstWalker::visitTable(Table* curr) {
+ for (auto& segment : curr->segments) {
+ for (auto& name : segment.data) {
+ auto* func = wasm.getFunction(name);
+ if (func->imported() && func->base.hasSubstring(EMSCRIPTEN_ASM_CONST)) {
+ std::string baseSig = getSig(func);
+ fixupNameWithSig(name, baseSig);
+ }
}
}
}
@@ -416,6 +424,18 @@ void AsmConstWalker::process() {
addImports();
}
+std::string AsmConstWalker::fixupNameWithSig(Name& name, std::string baseSig) {
+ auto sig = asmConstSig(baseSig);
+ auto importName = nameForImportWithSig(sig);
+ name = importName;
+
+ if (allSigs.count(sig) == 0) {
+ allSigs.insert(sig);
+ queueImport(importName, baseSig);
+ }
+ return sig;
+}
+
Literal AsmConstWalker::idLiteralForCode(std::string code) {
int32_t id;
if (ids.count(code) == 0) {
diff --git a/test/lld/em_asm_table.wast b/test/lld/em_asm_table.wast
new file mode 100644
index 000000000..01039bf09
--- /dev/null
+++ b/test/lld/em_asm_table.wast
@@ -0,0 +1,13 @@
+(module
+ (type $0 (func (param i32 i32)))
+ (type $1 (func (param i32 i32 i32) (result i32)))
+ (import "env" "memory" (memory $2 8192))
+ (import "env" "emscripten_log" (func $fimport$0 (param i32 i32)))
+ (import "env" "emscripten_asm_const_int" (func $fimport$1 (param i32 i32 i32) (result i32)))
+ (table $0 159609 anyfunc)
+ (elem (i32.const 1) $fimport$0 $fimport$1)
+ (global $global$0 (mut i32) (i32.const 1024))
+ (global $global$1 i32 (i32.const 1048))
+ (export "__data_end" (global $global$1))
+)
+
diff --git a/test/lld/em_asm_table.wast.out b/test/lld/em_asm_table.wast.out
new file mode 100644
index 000000000..8d99e9a6f
--- /dev/null
+++ b/test/lld/em_asm_table.wast.out
@@ -0,0 +1,64 @@
+(module
+ (type $0 (func (param i32 i32)))
+ (type $1 (func (param i32 i32 i32) (result i32)))
+ (type $FUNCSIG$vii (func (param i32 i32)))
+ (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
+ (import "env" "memory" (memory $0 8192))
+ (import "env" "emscripten_log" (func $fimport$0 (param i32 i32)))
+ (import "env" "emscripten_asm_const_iii" (func $emscripten_asm_const_iii (param i32 i32 i32) (result i32)))
+ (table $0 159609 anyfunc)
+ (elem (i32.const 1) $fimport$0 $emscripten_asm_const_iii)
+ (global $global$0 (mut i32) (i32.const 1024))
+ (global $global$1 i32 (i32.const 1048))
+ (export "__data_end" (global $global$1))
+ (export "stackSave" (func $stackSave))
+ (export "stackAlloc" (func $stackAlloc))
+ (export "stackRestore" (func $stackRestore))
+ (export "__growWasmMemory" (func $__growWasmMemory))
+ (export "dynCall_vii" (func $dynCall_vii))
+ (export "dynCall_iiii" (func $dynCall_iiii))
+ (func $stackSave (; 2 ;) (result i32)
+ (get_global $global$0)
+ )
+ (func $stackAlloc (; 3 ;) (param $0 i32) (result i32)
+ (local $1 i32)
+ (set_global $global$0
+ (tee_local $1
+ (i32.and
+ (i32.sub
+ (get_global $global$0)
+ (get_local $0)
+ )
+ (i32.const -16)
+ )
+ )
+ )
+ (get_local $1)
+ )
+ (func $stackRestore (; 4 ;) (param $0 i32)
+ (set_global $global$0
+ (get_local $0)
+ )
+ )
+ (func $__growWasmMemory (; 5 ;) (param $newSize i32) (result i32)
+ (grow_memory
+ (get_local $newSize)
+ )
+ )
+ (func $dynCall_vii (; 6 ;) (param $fptr i32) (param $0 i32) (param $1 i32)
+ (call_indirect (type $FUNCSIG$vii)
+ (get_local $0)
+ (get_local $1)
+ (get_local $fptr)
+ )
+ )
+ (func $dynCall_iiii (; 7 ;) (param $fptr i32) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+ (call_indirect (type $FUNCSIG$iiii)
+ (get_local $0)
+ (get_local $1)
+ (get_local $2)
+ (get_local $fptr)
+ )
+ )
+)
+;; METADATA: { "asmConsts": {},"staticBump": 480, "initializers": [], "declares": ["emscripten_log"], "externs": [], "implementedFunctions": ["_stackSave","_stackAlloc","_stackRestore","___growWasmMemory","_dynCall_vii","_dynCall_iiii"], "exports": ["__data_end","stackSave","stackAlloc","stackRestore","__growWasmMemory","dynCall_vii","dynCall_iiii"], "invokeFuncs": [] }