summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/test/wasm/export-all.ll45
-rw-r--r--lld/wasm/Config.h1
-rw-r--r--lld/wasm/Driver.cpp8
-rw-r--r--lld/wasm/Options.td3
-rw-r--r--lld/wasm/Writer.cpp12
5 files changed, 64 insertions, 5 deletions
diff --git a/lld/test/wasm/export-all.ll b/lld/test/wasm/export-all.ll
new file mode 100644
index 00000000000..450c6e38e84
--- /dev/null
+++ b/lld/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
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 4b11320e7cf..76a78056707 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -23,6 +23,7 @@ struct Configuration {
bool CompressRelocTargets;
bool Demangle;
bool DisableVerify;
+ bool ExportAll;
bool ExportTable;
bool GcSections;
bool ImportMemory;
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 5a9fe3632b6..70a36046ad9 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -319,6 +319,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
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 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
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 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
WasmSym::CallCtors = Symtab->addSyntheticFunction(
"__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(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);
diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td
index 4dbed35595c..d627d7a11d4 100644
--- a/lld/wasm/Options.td
+++ b/lld/wasm/Options.td
@@ -105,6 +105,9 @@ def allow_undefined_file_s: Separate<["-"], "allow-undefined-file">,
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">;
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index ee6056ab76d..70d52bdb72d 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -742,7 +742,9 @@ void Writer::calculateExports() {
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 @@ void Writer::calculateExports() {
if (auto *F = dyn_cast<DefinedFunction>(Sym)) {
Export = {Name, WASM_EXTERNAL_FUNCTION, F->getFunctionIndex()};
} else if (auto *G = dyn_cast<DefinedGlobal>(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<DefinedData>(Sym);
OpenPOWER on IntegriCloud