From 1ee1d55621b16b30ff95246a0a3a76117ddd7571 Mon Sep 17 00:00:00 2001 From: Derek Schuff Date: Tue, 14 Jun 2016 10:12:55 -0700 Subject: [PATCH] Only export functions with default visibility As discussed in #585, this change makes s2wasm more aware of the symbol visibility output from LLVM, and only exports global functions with default visibility (instead of all globals as before). --- src/s2wasm.h | 9 ++++++++- src/wasm-linker.cpp | 13 +++++++++++-- src/wasm-linker.h | 5 +++++ test/dot_s/alias.wast | 2 -- test/dot_s/bcp-1.wast | 17 ----------------- test/dot_s/debug.wast | 1 - test/dot_s/dyncall.wast | 5 ----- test/dot_s/indirect-import.wast | 2 -- test/dot_s/visibilities.wast | 3 --- test/llvm_autogenerated/reg-stackify.wast | 1 - test/llvm_autogenerated/store-results.wast | 1 - 11 files changed, 24 insertions(+), 35 deletions(-) diff --git a/src/s2wasm.h b/src/s2wasm.h index bf66f440729..5eae6598017 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -399,7 +399,10 @@ class S2WasmBuilder { s++; if (match("text")) parseText(); else if (match("type")) parseType(); - else if (match("weak") || match("hidden") || match("protected") || match("internal")) getStr(); // contents are in the content that follows + else if (match("weak")) getStr(); // contents are in the content that follows + else if (match("hidden")) parseVisibility(LinkerObject::Visibility::kHidden); + else if (match("internal")) parseVisibility(LinkerObject::Visibility::kInternal); + else if (match("protected")) parseVisibility(LinkerObject::Visibility::kProtected); else if (match("imports")) skipImports(); else if (match("data")) {} else if (match("ident")) skipToEOL(); @@ -481,6 +484,10 @@ class S2WasmBuilder { WASM_UNUSED(filename); // TODO: use the filename } + void parseVisibility(LinkerObject::Visibility vis) { + linkerObj->setVisibility(getStr(), vis); + skipWhitespace(); + } void parseGlobl() { linkerObj->addGlobal(getStr()); skipWhitespace(); diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp index e6a0a0514eb..fe95b9739ce 100644 --- a/src/wasm-linker.cpp +++ b/src/wasm-linker.cpp @@ -115,8 +115,17 @@ void Linker::layout() { if (userMaxMemory) out.wasm.memory.max = userMaxMemory / Memory::kPageSize; out.wasm.memory.exportName = MEMORY; - // XXX For now, export all functions marked .globl. - for (Name name : out.globls) exportFunction(name, false); + // Export all globl functions with default visibility. Since .s files usually + // only output visibility information if it is not default, symbols are + // considered to have default visibility if they are not in the visibility table. + // Also export main for now because emscripten and the binaryen-shell tests use it. + for (Name name : out.globls) { + if (out.visibilities.count(name) == 0 || + out.visibilities.at(name) == LinkerObject::Visibility::kDefault || + name == "main") { + exportFunction(name, false); + } + } for (Name name : out.initializerFunctions) exportFunction(name, true); auto ensureFunctionIndex = [this](Name name) { diff --git a/src/wasm-linker.h b/src/wasm-linker.h index 97e1c9cd5ee..808b8927f4d 100644 --- a/src/wasm-linker.h +++ b/src/wasm-linker.h @@ -67,6 +67,7 @@ class LinkerObject { other.aliasedFunctions.end()); } }; + enum class Visibility { kDefault, kInternal, kHidden, kProtected }; LinkerObject() {} @@ -75,6 +76,9 @@ class LinkerObject { staticObjects.emplace_back(allocSize, alignment, name); } + void setVisibility(Name name, Visibility vis) { + visibilities[name] = vis; + } void addGlobal(Name name) { globls.push_back(name); } @@ -145,6 +149,7 @@ class LinkerObject { allocSize(allocSize), alignment(alignment), name(name) {} }; + std::unordered_map visibilities; std::vector globls; std::vector staticObjects; diff --git a/test/dot_s/alias.wast b/test/dot_s/alias.wast index d1e08e136a9..0bbd4142be3 100644 --- a/test/dot_s/alias.wast +++ b/test/dot_s/alias.wast @@ -2,8 +2,6 @@ (memory 1) (export "memory" memory) (type $FUNCSIG$v (func)) - (export "__exit" $__exit) - (export "__needs_exit" $__needs_exit) (export "dynCall_v" $dynCall_v) (table $__exit) (func $__exit (type $FUNCSIG$v) diff --git a/test/dot_s/bcp-1.wast b/test/dot_s/bcp-1.wast index 0525be43813..2e94f22c92e 100644 --- a/test/dot_s/bcp-1.wast +++ b/test/dot_s/bcp-1.wast @@ -15,23 +15,6 @@ (type $FUNCSIG$vi (func (param i32))) (import $abort "env" "abort") (import $exit "env" "exit" (param i32)) - (export "bad0" $bad0) - (export "bad1" $bad1) - (export "bad2" $bad2) - (export "bad3" $bad3) - (export "bad4" $bad4) - (export "bad5" $bad5) - (export "bad6" $bad6) - (export "bad7" $bad7) - (export "bad8" $bad8) - (export "bad9" $bad9) - (export "bad10" $bad10) - (export "good0" $good0) - (export "good1" $good1) - (export "good2" $good2) - (export "opt0" $opt0) - (export "opt1" $opt1) - (export "opt2" $opt2) (export "main" $main) (export "dynCall_i" $dynCall_i) (export "dynCall_ii" $dynCall_ii) diff --git a/test/dot_s/debug.wast b/test/dot_s/debug.wast index 3a859fd0d66..d17be665d89 100644 --- a/test/dot_s/debug.wast +++ b/test/dot_s/debug.wast @@ -1,7 +1,6 @@ (module (memory 1) (export "memory" memory) - (export "fib" $fib) (func $fib (param $0 i32) (result i32) (local $1 i32) (local $2 i32) diff --git a/test/dot_s/dyncall.wast b/test/dot_s/dyncall.wast index b0521de84c3..9cb81edbc0c 100644 --- a/test/dot_s/dyncall.wast +++ b/test/dot_s/dyncall.wast @@ -5,11 +5,6 @@ (type $FUNCSIG$if (func (param f32) (result i32))) (type $FUNCSIG$vd (func (param f64))) (type $FUNCSIG$ffjjdi (func (param f32 i64 i64 f64 i32) (result f32))) - (export "i" $i) - (export "i_f" $i_f) - (export "vd" $vd) - (export "ffjjdi" $ffjjdi) - (export "vd2" $vd2) (export "main" $main) (export "dynCall_i" $dynCall_i) (export "dynCall_if" $dynCall_if) diff --git a/test/dot_s/indirect-import.wast b/test/dot_s/indirect-import.wast index 21378eefa12..2eb506fb67f 100644 --- a/test/dot_s/indirect-import.wast +++ b/test/dot_s/indirect-import.wast @@ -12,8 +12,6 @@ (import $extern_fd "env" "extern_fd" (param f64) (result f32)) (import $extern_struct "env" "extern_struct" (param i32)) (import $extern_sret "env" "extern_sret" (param i32)) - (export "bar" $bar) - (export "baz" $baz) (export "dynCall_fd" $dynCall_fd) (export "dynCall_v" $dynCall_v) (export "dynCall_vi" $dynCall_vi) diff --git a/test/dot_s/visibilities.wast b/test/dot_s/visibilities.wast index cfd504026a2..58791908298 100644 --- a/test/dot_s/visibilities.wast +++ b/test/dot_s/visibilities.wast @@ -1,9 +1,6 @@ (module (memory 1) (export "memory" memory) - (export "foo" $foo) - (export "bar" $bar) - (export "qux" $qux) (func $foo (return) ) diff --git a/test/llvm_autogenerated/reg-stackify.wast b/test/llvm_autogenerated/reg-stackify.wast index eea7e8bbffe..652b078db38 100644 --- a/test/llvm_autogenerated/reg-stackify.wast +++ b/test/llvm_autogenerated/reg-stackify.wast @@ -31,7 +31,6 @@ (export "no_sink_readonly_call" $no_sink_readonly_call) (export "stack_uses" $stack_uses) (export "multiple_uses" $multiple_uses) - (export "stackify_store_across_side_effects" $stackify_store_across_side_effects) (export "div_tree" $div_tree) (export "simple_multiple_use" $simple_multiple_use) (export "multiple_uses_in_same_insn" $multiple_uses_in_same_insn) diff --git a/test/llvm_autogenerated/store-results.wast b/test/llvm_autogenerated/store-results.wast index dd974db2948..f67c4d8d0c9 100644 --- a/test/llvm_autogenerated/store-results.wast +++ b/test/llvm_autogenerated/store-results.wast @@ -6,7 +6,6 @@ (export "single_block" $single_block) (export "foo" $foo) (export "bar" $bar) - (export "fi_ret" $fi_ret) (func $single_block (param $0 i32) (result i32) (return (i32.store