Index: test/wasm/export-all.ll =================================================================== --- /dev/null +++ test/wasm/export-all.ll @@ -0,0 +1,45 @@ +; RUN: llc -O0 -filetype=obj %s -o %t.o + +; RUN: wasm-ld -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck %s + +; RUN: wasm-ld --export-all -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck %s -check-prefix=EXPORT + +; RUN: wasm-ld --export-all --no-gc-sections -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck %s -check-prefix=NOGC + +; Verify the --export-all flag exports hidden symbols + +target triple = "wasm32-unknown-unknown" + +define hidden void @bar() local_unnamed_addr { +entry: + ret void +} + +define hidden void @foo() local_unnamed_addr { +entry: + ret void +} + +define hidden void @_start() local_unnamed_addr { +entry: + call void @foo() + ret void +} + +; CHECK: - Type: EXPORT +; CHECK: - Name: _start +; CHECK-NOT: - Name: bar +; CHECK-NOT: - Name: foo + +; EXPORT: - Type: EXPORT +; EXPORT: - Name: _start +; EXPORT-NOT: - Name: bar +; EXPORT: - Name: foo + +; NOGC: - Type: EXPORT +; NOGC: - Name: _start +; NOGC: - Name: bar +; NOGC: - Name: foo Index: wasm/Config.h =================================================================== --- wasm/Config.h +++ wasm/Config.h @@ -23,6 +23,7 @@ bool CompressRelocTargets; bool Demangle; bool DisableVerify; + bool ExportAll; bool ExportTable; bool GcSections; bool ImportMemory; Index: wasm/Driver.cpp =================================================================== --- wasm/Driver.cpp +++ wasm/Driver.cpp @@ -319,6 +319,7 @@ Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true); Config->DisableVerify = Args.hasArg(OPT_disable_verify); Config->Entry = getEntry(Args, Args.hasArg(OPT_relocatable) ? "" : "_start"); + Config->ExportAll = Args.hasArg(OPT_export_all); Config->ExportTable = Args.hasArg(OPT_export_table); errorHandler().FatalWarnings = Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); @@ -389,10 +390,6 @@ Symbol *EntrySym = nullptr; if (!Config->Relocatable) { - // Can't export the SP right now because it's mutable, and mutable - // globals aren't yet supported in the official binary format. - // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN if/when the - // "mutable global" proposal is accepted. llvm::wasm::WasmGlobal Global; Global.Type = {WASM_TYPE_I32, true}; Global.InitExpr.Value.Int32 = 0; @@ -407,6 +404,9 @@ WasmSym::CallCtors = Symtab->addSyntheticFunction( "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN, make(NullSignature, "__wasm_call_ctors")); + // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN when the mutable global + // spec proposal is implemented in all major browsers. + // See: https://github.com/WebAssembly/mutable-global WasmSym::StackPointer = Symtab->addSyntheticGlobal( "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer); WasmSym::HeapBase = Symtab->addSyntheticDataSymbol("__heap_base", 0); Index: wasm/Options.td =================================================================== --- wasm/Options.td +++ wasm/Options.td @@ -105,6 +105,9 @@ defm export: Eq<"export">, HelpText<"Force a symbol to be exported">; +def export_all: F<"export-all">, + HelpText<"Export all symbols (normally combined with --no-gc-sections)">; + def export_table: F<"export-table">, HelpText<"Export function table to the environment">; Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -742,7 +742,9 @@ for (Symbol *Sym : Symtab->getSymbols()) { if (!Sym->isDefined()) continue; - if (Sym->isHidden() || Sym->isLocal()) + if (Sym->isHidden() && !Config->ExportAll) + continue; + if (Sym->isLocal()) continue; if (!Sym->isLive()) continue; @@ -752,6 +754,14 @@ if (auto *F = dyn_cast(Sym)) { Export = {Name, WASM_EXTERNAL_FUNCTION, F->getFunctionIndex()}; } else if (auto *G = dyn_cast(Sym)) { + // TODO(sbc): Remove this check once to mutable global proposal is + // implement in all major browsers. + // See: https://github.com/WebAssembly/mutable-global + if (G->getGlobalType()->Mutable) { + // Only the __stack_pointer should ever be create as mutable. + assert(G == WasmSym::StackPointer); + continue; + } Export = {Name, WASM_EXTERNAL_GLOBAL, G->getGlobalIndex()}; } else { auto *D = cast(Sym);