; 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
+; RUN: obj2yaml %t.wasm | FileCheck %s -check-prefix=EXPORT
; Verify the --export-all flag exports hidden symbols
target triple = "wasm32-unknown-unknown"
+define internal void @internal_func() local_unnamed_addr {
+entry:
+ ret void
+}
+
define hidden void @bar() local_unnamed_addr {
entry:
ret void
define hidden void @_start() local_unnamed_addr {
entry:
call void @foo()
+ call void @internal_func()
ret void
}
; CHECK: - Name: _start
; CHECK-NOT: - Name: bar
; CHECK-NOT: - Name: foo
+; CHECK-NOT: - Name: internal_func
; EXPORT: - Type: EXPORT
; EXPORT: - Name: _start
-; EXPORT-NOT: - Name: bar
+; EXPORT: - Name: bar
; EXPORT: - Name: foo
-
-; NOGC: - Type: EXPORT
-; NOGC: - Name: _start
-; NOGC: - Name: bar
-; NOGC: - Name: foo
+; EXPORT-NOT: - Name: internal_func
--- /dev/null
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown"
+
+define void @f() {
+ ret void
+}
--- /dev/null
+; RUN: llvm-as %S/Inputs/archive.ll -o %t1.o
+; RUN: rm -f %t.a
+; RUN: llvm-ar rcs %t.a %t1.o
+; RUN: llvm-as %s -o %t2.o
+; RUN: wasm-ld %t2.o %t.a -o %t3
+; RUN: obj2yaml %t3 | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown"
+
+define void @_start() {
+ call void @f()
+ ret void
+}
+
+declare void @f()
+
+; CHECK: Name: name
+; CHECK-NEXT: FunctionNames:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: __wasm_call_ctors
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: _start
+; CHECK-NEXT: - Index: 2
+; CHECK-NEXT: Name: f
"could not get the buffer for the member defining symbol " +
Sym->getName());
- if (identify_magic(MB.getBuffer()) != file_magic::wasm_object) {
+ InputFile *Obj;
+
+ file_magic Magic = identify_magic(MB.getBuffer());
+ if (Magic == file_magic::wasm_object) {
+ Obj = make<ObjFile>(MB);
+ } else if (Magic == file_magic::bitcode) {
+ Obj = make<BitcodeFile>(MB);
+ } else {
error("unknown file type: " + MB.getBufferIdentifier());
return;
}
- InputFile *Obj = make<ObjFile>(MB);
Obj->ParentName = ParentName;
Symtab->addFile(Obj);
}
// Once IRObjectFile is fixed to report only one symbol this hack can
// be removed.
R.Prevailing = !ObjSym.isUndefined() && Sym->getFile() == &F;
- R.VisibleToRegularObj = Config->Relocatable || Sym->IsUsedInRegularObj;
+ R.VisibleToRegularObj = Config->Relocatable || Sym->IsUsedInRegularObj ||
+ (R.Prevailing && Sym->isExported());
if (R.Prevailing)
undefine(Sym);
}
Enqueue(Symtab->find(Config->Entry));
Enqueue(WasmSym::CallCtors);
- // We export all defined, non-hidden symbols so they are all gc roots too
+ // We need to preserve any exported symbol
for (Symbol *Sym : Symtab->getSymbols())
- if (Sym->isDefined() && !Sym->isHidden())
+ if (Sym->isExported())
Enqueue(Sym);
// The ctor functions are all used in the synthetic __wasm_call_ctors
Flags |= WASM_SYMBOL_VISIBILITY_DEFAULT;
}
+bool Symbol::isExported() const {
+ if (!isDefined() || isLocal())
+ return false;
+
+ if (Config->ExportAll)
+ return true;
+
+ return !isHidden();
+}
+
uint32_t FunctionSymbol::getFunctionIndex() const {
if (auto *F = dyn_cast<DefinedFunction>(this))
return F->Function->getFunctionIndex();
void setOutputSymbolIndex(uint32_t Index);
WasmSymbolType getWasmType() const;
+ bool isExported() const;
// True if this symbol was referenced by a regular (non-bitcode) object.
unsigned IsUsedInRegularObj : 1;
unsigned FakeGlobalIndex = NumImportedGlobals + InputGlobals.size();
for (Symbol *Sym : Symtab->getSymbols()) {
- if (!Sym->isDefined())
- continue;
- if (Sym->isHidden() && !Config->ExportAll)
- continue;
- if (Sym->isLocal())
+ if (!Sym->isExported())
continue;
if (!Sym->isLive())
continue;