diff --git a/lld/test/wasm/export-all.s b/lld/test/wasm/export-all.s new file mode 100644 --- /dev/null +++ b/lld/test/wasm/export-all.s @@ -0,0 +1,48 @@ +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s +# RUN: wasm-ld --export-all -o %t.wasm %t.o +# RUN: obj2yaml %t.wasm | FileCheck %s + +.globl _start + +_start: + .functype _start () -> () + i32.const 3 + global.set __stack_pointer + end_function + +foo: + .functype foo () -> (i32) + i32.const 42 + end_function + +.globaltype __stack_pointer, i32 + +# CHECK: - Type: EXPORT +# CHECK-NEXT: Exports: +# CHECK-NEXT: - Name: memory +# CHECK-NEXT: Kind: MEMORY +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: - Name: __wasm_call_ctors +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: - Name: _start +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: - Name: __dso_handle +# CHECK-NEXT: Kind: GLOBAL +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: - Name: __data_end +# CHECK-NEXT: Kind: GLOBAL +# CHECK-NEXT: Index: 2 +# CHECK-NEXT: - Name: __global_base +# CHECK-NEXT: Kind: GLOBAL +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: - Name: __heap_base +# CHECK-NEXT: Kind: GLOBAL +# CHECK-NEXT: Index: 4 +# CHECK-NEXT: - Name: __memory_base +# CHECK-NEXT: Kind: GLOBAL +# CHECK-NEXT: Index: 5 +# CHECK-NEXT: - Name: __table_base +# CHECK-NEXT: Kind: GLOBAL +# CHECK-NEXT: Index: 6 diff --git a/lld/test/wasm/mutable-globals.s b/lld/test/wasm/mutable-globals.s --- a/lld/test/wasm/mutable-globals.s +++ b/lld/test/wasm/mutable-globals.s @@ -1,5 +1,5 @@ # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s -# RUN: not wasm-ld %t.o -o %t.wasm 2>&1 | FileCheck %s +# RUN: not wasm-ld --allow-undefined %t.o -o %t.wasm 2>&1 | FileCheck %s .globl _start _start: diff --git a/lld/wasm/SyntheticSections.h b/lld/wasm/SyntheticSections.h --- a/lld/wasm/SyntheticSections.h +++ b/lld/wasm/SyntheticSections.h @@ -221,6 +221,7 @@ void writeBody() override; std::vector exports; + std::vector exportedSymbols; }; class StartSection : public SyntheticSection { diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -463,26 +463,22 @@ return; if (!config->relocatable && used.count("mutable-globals") == 0) { - for (Symbol *sym : symtab->getSymbols()) { + for (const Symbol *sym : out.importSec->importedSymbols) { if (auto *global = dyn_cast(sym)) { if (global->getGlobalType()->Mutable) { - if (!sym->isLive()) - continue; - if (!sym->isUsedInRegularObj) - continue; - if (sym->isUndefined() && sym->isWeak() && !config->relocatable) - continue; - if (sym->isUndefined()) - error(Twine("mutable global imported but 'mutable-globals' feature " - "not present in inputs: `") + - toString(*sym) + "`. Use --no-check-features to suppress."); - else if (sym->isExported()) - error(Twine("mutable global exported but 'mutable-globals' feature " - "not present in inputs: `") + - toString(*sym) + "`. Use --no-check-features to suppress."); + error(Twine("mutable global imported but 'mutable-globals' feature " + "not present in inputs: `") + + toString(*sym) + "`. Use --no-check-features to suppress."); } } } + for (const Symbol *sym : out.exportSec->exportedSymbols) { + if (auto *global = dyn_cast(sym)) { + error(Twine("mutable global exported but 'mutable-globals' feature " + "not present in inputs: `") + + toString(*sym) + "`. Use --no-check-features to suppress."); + } + } } if (config->sharedMemory) { @@ -603,6 +599,7 @@ LLVM_DEBUG(dbgs() << "Export: " << name << "\n"); out.exportSec->exports.push_back(export_); + out.exportSec->exportedSymbols.push_back(sym); } } @@ -1075,8 +1072,6 @@ createSyntheticSections(); log("-- populateProducers"); populateProducers(); - log("-- populateTargetFeatures"); - populateTargetFeatures(); log("-- calculateImports"); calculateImports(); log("-- layoutMemory"); @@ -1119,6 +1114,8 @@ calculateCustomSections(); log("-- populateSymtab"); populateSymtab(); + log("-- populateTargetFeatures"); + populateTargetFeatures(); log("-- addSections"); addSections();