[WebAssembly] Add --export-all flag

This causes all symbols to be exported in the final wasm binary
even if they were not compiled with default visibility.

This feature is useful for the emscripten toolchain that has a
corresponding EXPORT_ALL feature which allows the JS code to
interact with all C function.

Differential Revision: https://reviews.llvm.org/D47806

llvm-svn: 334157
This commit is contained in:
Sam Clegg 2018-06-07 01:27:07 +00:00
parent 7a88f19099
commit 177b458c8a
5 changed files with 64 additions and 5 deletions

View File

@ -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

View File

@ -23,6 +23,7 @@ struct Configuration {
bool CompressRelocTargets;
bool Demangle;
bool DisableVerify;
bool ExportAll;
bool ExportTable;
bool GcSections;
bool ImportMemory;

View File

@ -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);

View File

@ -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">;

View File

@ -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);