summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm/wasm-emscripten.cpp12
-rw-r--r--test/lld/duplicate_imports.wast32
-rw-r--r--test/lld/duplicate_imports.wast.out68
3 files changed, 110 insertions, 2 deletions
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index c70069e76..580510ecb 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -724,6 +724,12 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
meta << "]";
}
+ // Avoid adding duplicate imports to `declares' or `invokeFuncs`. Even
+ // though we might import the same function multiple times (i.e. with
+ // different sigs) we only need to list is in the metadata once.
+ std::set<std::string> declares;
+ std::set<std::string> invokeFuncs;
+
// We use the `base` rather than the `name` of the imports here and below
// becasue this is the externally visible name that the embedder (JS) will
// see.
@@ -735,7 +741,8 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
!import->base.startsWith(EMSCRIPTEN_ASM_CONST.str) &&
!import->base.startsWith("invoke_") &&
!import->base.startsWith("jsCall_")) {
- meta << maybeComma() << '"' << import->base.str << '"';
+ if (declares.insert(import->base.str).second)
+ meta << maybeComma() << '"' << import->base.str << '"';
}
}
meta << "]";
@@ -769,7 +776,8 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
commaFirst = true;
for (const auto& import : wasm.imports) {
if (import->base.startsWith("invoke_")) {
- meta << maybeComma() << '"' << import->base.str << '"';
+ if (invokeFuncs.insert(import->base.str).second)
+ meta << maybeComma() << '"' << import->base.str << '"';
}
}
meta << "]";
diff --git a/test/lld/duplicate_imports.wast b/test/lld/duplicate_imports.wast
new file mode 100644
index 000000000..8147f5d2f
--- /dev/null
+++ b/test/lld/duplicate_imports.wast
@@ -0,0 +1,32 @@
+(module
+ (type $0 (func (param i32) (result i32)))
+ (type $1 (func (result i32)))
+ (type $2 (func))
+ (import "env" "puts" (func $puts1 (param i32) (result i32)))
+ (import "env" "puts" (func $puts2 (param i64) (result i32)))
+ (import "env" "invoke_ffd" (func $invoke_ffd (param i32 f32 f64) (result f32)))
+ (import "env" "invoke_ffd" (func $invoke_ffd2 (param i32 f64 f64) (result f32)))
+ (global $global$0 (mut i32) (i32.const 66128))
+ (global $global$1 i32 (i32.const 66128))
+ (global $global$2 i32 (i32.const 581))
+ (table 1 1 anyfunc)
+ (memory $0 2)
+ (data (i32.const 568) "Hello, world\00")
+ (export "memory" (memory $0))
+ (export "__wasm_call_ctors" (func $__wasm_call_ctors))
+ (export "main" (func $main))
+ (export "__heap_base" (global $global$1))
+ (export "__data_end" (global $global$2))
+ (func $main (; 1 ;) (type $1) (result i32)
+ (drop
+ (call $puts1
+ (i32.const 568)
+ )
+ )
+ (i32.const 0)
+ )
+ (func $__wasm_call_ctors (; 2 ;) (type $2)
+ )
+ ;; custom section "linking", size 3
+)
+
diff --git a/test/lld/duplicate_imports.wast.out b/test/lld/duplicate_imports.wast.out
new file mode 100644
index 000000000..71c652126
--- /dev/null
+++ b/test/lld/duplicate_imports.wast.out
@@ -0,0 +1,68 @@
+(module
+ (type $0 (func (param i32) (result i32)))
+ (type $1 (func (result i32)))
+ (type $2 (func))
+ (type $FUNCSIG$ii (func (param i32) (result i32)))
+ (type $FUNCSIG$ij (func (param i64) (result i32)))
+ (type $FUNCSIG$fifd (func (param i32 f32 f64) (result f32)))
+ (type $FUNCSIG$fidd (func (param i32 f64 f64) (result f32)))
+ (import "env" "puts" (func $puts1 (param i32) (result i32)))
+ (import "env" "puts" (func $puts2 (param i64) (result i32)))
+ (import "env" "invoke_ffd" (func $invoke_ffd (param i32 f32 f64) (result f32)))
+ (import "env" "invoke_ffd" (func $invoke_ffd2 (param i32 f64 f64) (result f32)))
+ (global $global$0 (mut i32) (i32.const 66128))
+ (global $global$1 i32 (i32.const 66128))
+ (global $global$2 i32 (i32.const 581))
+ (table 1 1 anyfunc)
+ (memory $0 2)
+ (data (i32.const 568) "Hello, world\00")
+ (export "memory" (memory $0))
+ (export "__wasm_call_ctors" (func $__wasm_call_ctors))
+ (export "main" (func $main))
+ (export "__heap_base" (global $global$1))
+ (export "__data_end" (global $global$2))
+ (export "stackSave" (func $stackSave))
+ (export "stackAlloc" (func $stackAlloc))
+ (export "stackRestore" (func $stackRestore))
+ (export "__growWasmMemory" (func $__growWasmMemory))
+ (func $main (; 4 ;) (type $1) (result i32)
+ (drop
+ (call $puts1
+ (i32.const 568)
+ )
+ )
+ (i32.const 0)
+ )
+ (func $__wasm_call_ctors (; 5 ;) (type $2)
+ (nop)
+ )
+ (func $stackSave (; 6 ;) (result i32)
+ (get_global $global$0)
+ )
+ (func $stackAlloc (; 7 ;) (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 (; 8 ;) (param $0 i32)
+ (set_global $global$0
+ (get_local $0)
+ )
+ )
+ (func $__growWasmMemory (; 9 ;) (param $newSize i32) (result i32)
+ (grow_memory
+ (get_local $newSize)
+ )
+ )
+)
+;; METADATA: { "asmConsts": {},"staticBump": 13, "initializers": ["__wasm_call_ctors"], "declares": ["puts"], "externs": [], "implementedFunctions": ["___wasm_call_ctors","_main","_stackSave","_stackAlloc","_stackRestore","___growWasmMemory"], "exports": ["memory","__wasm_call_ctors","main","__heap_base","__data_end","stackSave","stackAlloc","stackRestore","__growWasmMemory"], "invokeFuncs": ["invoke_ffd"] }