--- /dev/null
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
+#
+# Should fail without mutable globals feature enabled.
+# RUN: not wasm-ld --export-all %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-ERR %s
+# RUN: not wasm-ld --export=foo_global %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-ERR %s
+#
+# RUN: wasm-ld --features=mutable-globals --export=foo_global %t.o -o %t.wasm
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+# Explcitly check that __stack_pointer can be exported
+# RUN: wasm-ld --features=mutable-globals --export=__stack_pointer %t.o -o %t.wasm
+# RUN: obj2yaml %t.wasm | FileCheck -check-prefix=CHECK-SP %s
+
+# RUN: wasm-ld --features=mutable-globals --export-all %t.o -o %t.wasm
+# RUN: obj2yaml %t.wasm | FileCheck -check-prefix=CHECK-ALL %s
+
+
+.globl _start
+.globl foo_global
+
+.globaltype foo_global, i32
+foo_global:
+
+_start:
+ .functype _start () -> ()
+ end_function
+
+# CHECK-ERR: mutable global exported but 'mutable-globals' feature not present in inputs: `foo_global`. Use --no-check-features to suppress
+
+# CHECK: - Type: EXPORT
+# CHECK-NEXT: Exports:
+# CHECK-NEXT: - Name: memory
+# CHECK-NEXT: Kind: MEMORY
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: - Name: _start
+# CHECK-NEXT: Kind: FUNCTION
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: - Name: foo_global
+# CHECK-NEXT: Kind: GLOBAL
+# CHECK-NEXT: Index: 1
+# CHECK-NEXT: - Type: CODE
+
+# CHECK-SP: - Type: EXPORT
+# CHECK-SP-NEXT: Exports:
+# CHECK-SP-NEXT: - Name: memory
+# CHECK-SP-NEXT: Kind: MEMORY
+# CHECK-SP-NEXT: Index: 0
+# CHECK-SP-NEXT: - Name: __stack_pointer
+# CHECK-SP-NEXT: Kind: GLOBAL
+# CHECK-SP-NEXT: Index: 0
+# CHECK-SP-NEXT: - Name: _start
+# CHECK-SP-NEXT: Kind: FUNCTION
+# CHECK-SP-NEXT: Index: 0
+# CHECK-SP-NEXT: - Type: CODE
+
+# CHECK-ALL: - Type: EXPORT
+# CHECK-ALL-NEXT: Exports:
+# CHECK-ALL-NEXT: - Name: memory
+# CHECK-ALL-NEXT: Kind: MEMORY
+# CHECK-ALL-NEXT: Index: 0
+# CHECK-ALL-NEXT: - Name: __wasm_call_ctors
+# CHECK-ALL-NEXT: Kind: FUNCTION
+# CHECK-ALL-NEXT: Index: 0
+# CHECK-ALL-NEXT: - Name: _start
+# CHECK-ALL-NEXT: Kind: FUNCTION
+# CHECK-ALL-NEXT: Index: 1
+# CHECK-ALL-NEXT: - Name: foo_global
+# CHECK-ALL-NEXT: Kind: GLOBAL
+# CHECK-ALL-NEXT: Index: 1
+# CHECK-ALL-NEXT: - Name: __dso_handle
+# CHECK-ALL-NEXT: Kind: GLOBAL
+# CHECK-ALL-NEXT: Index: 2
+# CHECK-ALL-NEXT: - Name: __data_end
+# CHECK-ALL-NEXT: Kind: GLOBAL
+# CHECK-ALL-NEXT: Index: 3
+# CHECK-ALL-NEXT: - Name: __global_base
+# CHECK-ALL-NEXT: Kind: GLOBAL
+# CHECK-ALL-NEXT: Index: 4
+# CHECK-ALL-NEXT: - Name: __heap_base
+# CHECK-ALL-NEXT: Kind: GLOBAL
+# CHECK-ALL-NEXT: Index: 5
+# CHECK-ALL-NEXT: - Name: __memory_base
+# CHECK-ALL-NEXT: Kind: GLOBAL
+# CHECK-ALL-NEXT: Index: 6
+# CHECK-ALL-NEXT: - Name: __table_base
+# CHECK-ALL-NEXT: Kind: GLOBAL
+# CHECK-ALL-NEXT: Index: 7
+# CHECK-ALL-NEXT: - Type: CODE
if (!config->checkFeatures)
return;
- if (!config->relocatable && used.count("mutable-globals") == 0) {
+ if (!config->relocatable && allowed.count("mutable-globals") == 0) {
for (const Symbol *sym : out.importSec->importedSymbols) {
if (auto *global = dyn_cast<GlobalSymbol>(sym)) {
if (global->getGlobalType()->Mutable) {
}
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 __stack_pointer and __tls_base should ever be create as mutable.
- assert(g == WasmSym::stackPointer || g == WasmSym::tlsBase);
+ if (g->getGlobalType()->Mutable && !g->getFile() && !g->forceExport) {
+ // Avoid exporting mutable globals are linker synthesized (e.g.
+ // __stack_pointer or __tls_base) unless they are explicitly exported
+ // from the command line.
+ // Without this check `--export-all` would cause any program using the
+ // stack pointer to export a mutable global even if none of the input
+ // files were built with the `mutable-globals` feature.
continue;
}
export_ = {name, WASM_EXTERNAL_GLOBAL, g->getGlobalIndex()};