diff options
-rw-r--r-- | src/wasm/wasm-emscripten.cpp | 12 | ||||
-rw-r--r-- | test/lld/duplicate_imports.wast | 32 | ||||
-rw-r--r-- | test/lld/duplicate_imports.wast.out | 68 |
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"] } |