summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/test/wasm/call-indirect.ll6
-rw-r--r--lld/test/wasm/cxx-mangling.ll6
-rw-r--r--lld/test/wasm/demangle.ll14
-rw-r--r--lld/test/wasm/export-all.ll2
-rw-r--r--lld/test/wasm/export.ll6
-rw-r--r--lld/test/wasm/load-undefined.test13
-rw-r--r--lld/test/wasm/lto/export.ll6
-rw-r--r--lld/test/wasm/undefined-entry.test8
-rw-r--r--lld/test/wasm/undefined.ll4
-rw-r--r--lld/test/wasm/visibility-hidden.ll6
-rw-r--r--lld/test/wasm/weak-alias-overide.ll6
-rw-r--r--lld/test/wasm/weak-undefined.ll6
-rw-r--r--lld/wasm/Driver.cpp66
-rw-r--r--lld/wasm/SymbolTable.cpp15
14 files changed, 71 insertions, 93 deletions
diff --git a/lld/test/wasm/call-indirect.ll b/lld/test/wasm/call-indirect.ll
index 63a6def8738..f5dc2208af4 100644
--- a/lld/test/wasm/call-indirect.ll
+++ b/lld/test/wasm/call-indirect.ll
@@ -105,9 +105,6 @@ define void @call_ptr(i64 (i64)* %arg) {
; CHECK-NEXT: - Name: __data_end
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 2
-; CHECK-NEXT: - Name: _start
-; CHECK-NEXT: Kind: FUNCTION
-; CHECK-NEXT: Index: 4
; CHECK-NEXT: - Name: bar
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 1
@@ -117,6 +114,9 @@ define void @call_ptr(i64 (i64)* %arg) {
; CHECK-NEXT: - Name: foo
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 3
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 4
; CHECK-NEXT: - Name: indirect_func
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 3
diff --git a/lld/test/wasm/cxx-mangling.ll b/lld/test/wasm/cxx-mangling.ll
index 67f3594e816..c7f15af4f90 100644
--- a/lld/test/wasm/cxx-mangling.ll
+++ b/lld/test/wasm/cxx-mangling.ll
@@ -32,12 +32,12 @@ define void @_start() {
; CHECK-NEXT: - Name: __data_end
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 2
-; CHECK-NEXT: - Name: _start
-; CHECK-NEXT: Kind: FUNCTION
-; CHECK-NEXT: Index: 3
; CHECK-NEXT: - Name: _Z3fooi
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 2
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 3
; CHECK-NEXT: - Type: CODE
; CHECK-NEXT: Functions:
; CHECK-NEXT: - Index: 0
diff --git a/lld/test/wasm/demangle.ll b/lld/test/wasm/demangle.ll
index f0416bb6b32..64fa46ae4dc 100644
--- a/lld/test/wasm/demangle.ll
+++ b/lld/test/wasm/demangle.ll
@@ -1,17 +1,19 @@
; RUN: llc -filetype=obj %s -o %t.o
-; RUN: not wasm-ld --undefined _Z3fooi \
-; RUN: -o %t.wasm %t.o 2>&1 | FileCheck %s
+; RUN: not wasm-ld -o %t.wasm %t.o 2>&1 | FileCheck %s
-; CHECK: error: undefined symbol: foo(int)
+; CHECK: error: {{.*}}.o: undefined symbol: foo(int)
-; RUN: not wasm-ld --no-demangle --undefined _Z3fooi \
-; RUN: -o %t.wasm %t.o 2>&1 | FileCheck -check-prefix=CHECK-NODEMANGLE %s
+; RUN: not wasm-ld --no-demangle \
+; RUN: -o %t.wasm %t.o 2>&1 | FileCheck -check-prefix=CHECK-NODEMANGLE %s
-; CHECK-NODEMANGLE: error: undefined symbol: _Z3fooi
+; CHECK-NODEMANGLE: error: {{.*}}.o: undefined symbol: _Z3fooi
target triple = "wasm32-unknown-unknown"
+declare void @_Z3fooi(i32);
+
define hidden void @_start() local_unnamed_addr {
entry:
+ call void @_Z3fooi(i32 1)
ret void
}
diff --git a/lld/test/wasm/export-all.ll b/lld/test/wasm/export-all.ll
index 34797aac76f..f903df9160d 100644
--- a/lld/test/wasm/export-all.ll
+++ b/lld/test/wasm/export-all.ll
@@ -42,7 +42,7 @@ entry:
; CHECK-NOT: - Name: internal_func
; EXPORT: - Type: EXPORT
-; EXPORT: - Name: _start
; EXPORT: - Name: bar
; EXPORT: - Name: foo
+; EXPORT: - Name: _start
; EXPORT-NOT: - Name: internal_func
diff --git a/lld/test/wasm/export.ll b/lld/test/wasm/export.ll
index 16b2b6ca57c..519aafebbe2 100644
--- a/lld/test/wasm/export.ll
+++ b/lld/test/wasm/export.ll
@@ -28,10 +28,10 @@ entry:
; CHECK-NEXT: - Name: __data_end
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 2
-; CHECK-NEXT: - Name: _start
-; CHECK-NEXT: Kind: FUNCTION
-; CHECK-NEXT: Index: 2
; CHECK-NEXT: - Name: hidden_function
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 1
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 2
; CHECK-NEXT: - Type: CODE
diff --git a/lld/test/wasm/load-undefined.test b/lld/test/wasm/load-undefined.test
index 7c00fcd2103..1b8d259d5b8 100644
--- a/lld/test/wasm/load-undefined.test
+++ b/lld/test/wasm/load-undefined.test
@@ -18,9 +18,9 @@
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Name: _start
; CHECK-NEXT: - Index: 2
-; CHECK-NEXT: Name: ret32
-; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Name: ret64
+; CHECK-NEXT: - Index: 3
+; CHECK-NEXT: Name: ret32
; CHECK-NEXT: ...
; NO-LOAD: Name: name
@@ -33,9 +33,6 @@
; NO-LOAD-NEXT: Name: ret64
; NO-LOAD-NEXT: ...
-; Verify that referencing a symbol that doesn't exist won't work
-; RUN: not wasm-ld %t.start.o -o %t.wasm -u symboldoesnotexist 2>&1 | FileCheck -check-prefix=CHECK-UNDEFINED1 %s
-; CHECK-UNDEFINED1: error: undefined symbol: symboldoesnotexist
-
-; RUN: not wasm-ld %t.start.o -o %t.wasm --undefined symboldoesnotexist --allow-undefined 2>&1 | FileCheck -check-prefix=CHECK-UNDEFINED2 %s
-; CHECK-UNDEFINED2: symbol forced with --undefined not found: symboldoesnotexist
+; Verify that referencing a symbol that is not found doesn't result in a link
+; failure. This matches the behaviour of the ELF linker.
+; RUN: wasm-ld %t.start.o -o %t.wasm -u symboldoesnotexist
diff --git a/lld/test/wasm/lto/export.ll b/lld/test/wasm/lto/export.ll
index 44ded6f147f..0ff0be504ed 100644
--- a/lld/test/wasm/lto/export.ll
+++ b/lld/test/wasm/lto/export.ll
@@ -29,10 +29,10 @@ entry:
; CHECK-NEXT: - Name: __data_end
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 2
-; CHECK-NEXT: - Name: _start
-; CHECK-NEXT: Kind: FUNCTION
-; CHECK-NEXT: Index: 2
; CHECK-NEXT: - Name: hidden_function
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 1
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 2
; CHECK-NEXT: - Type: CODE
diff --git a/lld/test/wasm/undefined-entry.test b/lld/test/wasm/undefined-entry.test
index ffa079ca638..a36212f2c9e 100644
--- a/lld/test/wasm/undefined-entry.test
+++ b/lld/test/wasm/undefined-entry.test
@@ -1,11 +1,9 @@
RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
RUN: not wasm-ld -o %t.wasm %t.ret32.o 2>&1 | FileCheck %s
+RUN: not wasm-ld --allow-undefined -o %t.wasm %t.ret32.o 2>&1 | FileCheck %s
RUN: not wasm-ld -entry=foo -o %t.wasm %t.ret32.o 2>&1 | FileCheck %s -check-prefix=CHECK-CUSTOM
-RUN: not wasm-ld --allow-undefined -o %t.wasm %t.ret32.o 2>&1 | FileCheck %s -check-prefix=CHECK-ALLOW
-CHECK: error: undefined symbol: _start
-CHECK-CUSTOM: error: undefined symbol: foo
-CHECK-ALLOW: error: entry symbol not defined (pass --no-entry to supress):
-_start
+CHECK: error: entry symbol not defined (pass --no-entry to supress): _start
+CHECK-CUSTOM: error: entry symbol not defined (pass --no-entry to supress): foo
RUN: wasm-ld --no-entry -o %t.wasm %t.ret32.o
diff --git a/lld/test/wasm/undefined.ll b/lld/test/wasm/undefined.ll
index 7d2161d2bcc..1da979fc076 100644
--- a/lld/test/wasm/undefined.ll
+++ b/lld/test/wasm/undefined.ll
@@ -1,10 +1,10 @@
; RUN: llc -filetype=obj %s -o %t.o
; RUN: wasm-ld --allow-undefined -o %t.wasm %t.o
-; Fails due to undefined 'foo' and also 'baz'
+; Fails due to undefined 'foo'
; RUN: not wasm-ld --undefined=baz -o %t.wasm %t.o 2>&1 | FileCheck %s
; CHECK: error: {{.*}}.o: undefined symbol: foo
-; CHECK: error: undefined symbol: baz
+; CHECK-NOT: undefined symbol: baz
; Succeeds if we pass a file containing 'foo' as --allow-undefined-file.
; RUN: echo 'foo' > %t.txt
diff --git a/lld/test/wasm/visibility-hidden.ll b/lld/test/wasm/visibility-hidden.ll
index 432ea82302a..f553c08159c 100644
--- a/lld/test/wasm/visibility-hidden.ll
+++ b/lld/test/wasm/visibility-hidden.ll
@@ -43,12 +43,12 @@ entry:
; CHECK-NEXT: - Name: __data_end
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 2
-; CHECK-NEXT: - Name: _start
-; CHECK-NEXT: Kind: FUNCTION
-; CHECK-NEXT: Index: 3
; CHECK-NEXT: - Name: objectDefault
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 2
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 3
; CHECK-NEXT: - Name: archiveDefault
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 5
diff --git a/lld/test/wasm/weak-alias-overide.ll b/lld/test/wasm/weak-alias-overide.ll
index 8b98f3347a1..a6a37f25c9d 100644
--- a/lld/test/wasm/weak-alias-overide.ll
+++ b/lld/test/wasm/weak-alias-overide.ll
@@ -74,12 +74,12 @@ entry:
; CHECK-NEXT: - Name: __data_end
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 2
-; CHECK-NEXT: - Name: _start
-; CHECK-NEXT: Kind: FUNCTION
-; CHECK-NEXT: Index: 2
; CHECK-NEXT: - Name: alias_fn
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 1
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 2
; CHECK-NEXT: - Name: direct_fn
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 3
diff --git a/lld/test/wasm/weak-undefined.ll b/lld/test/wasm/weak-undefined.ll
index 53b38bc32c3..048b91b133e 100644
--- a/lld/test/wasm/weak-undefined.ll
+++ b/lld/test/wasm/weak-undefined.ll
@@ -81,15 +81,15 @@ entry:
; CHECK-NEXT: - Name: __data_end
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 2
-; CHECK-NEXT: - Name: _start
-; CHECK-NEXT: Kind: FUNCTION
-; CHECK-NEXT: Index: 3
; CHECK-NEXT: - Name: get_address_of_foo
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 1
; CHECK-NEXT: - Name: get_address_of_global_var
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 2
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 3
; CHECK-NEXT: - Type: CODE
; CHECK-NEXT: Functions:
; CHECK-NEXT: - Index: 0
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 329b5ae80a9..8d73dab726e 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -329,14 +329,19 @@ static void handleWeakUndefines() {
}
// Force Sym to be entered in the output. Used for -u or equivalent.
-static Symbol *addUndefined(StringRef Name) {
- Symbol *S = Symtab->addUndefinedFunction(Name, 0, nullptr, nullptr);
+static Symbol *handleUndefined(StringRef Name) {
+ Symbol *Sym = Symtab->find(Name);
+ if (!Sym)
+ return nullptr;
// Since symbol S may not be used inside the program, LTO may
// eliminate it. Mark the symbol as "used" to prevent it.
- S->IsUsedInRegularObj = true;
+ Sym->IsUsedInRegularObj = true;
- return S;
+ if (auto *LazySym = dyn_cast<LazySymbol>(Sym))
+ LazySym->fetch();
+
+ return Sym;
}
void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
@@ -462,15 +467,6 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
WasmSym::DsoHandle = Symtab->addSyntheticDataSymbol(
"__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN);
WasmSym::DataEnd = Symtab->addSyntheticDataSymbol("__data_end", 0);
-
- // For now, since we don't actually use the start function as the
- // wasm start symbol, we don't need to care about it signature.
- if (!Config->Entry.empty())
- EntrySym = addUndefined(Config->Entry);
-
- // Handle the `--undefined <sym>` options.
- for (auto *Arg : Args.filtered(OPT_undefined))
- addUndefined(Arg->getValue());
}
createFiles(Args);
@@ -484,10 +480,29 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
if (errorCount())
return;
- // Add synthetic dummies for weak undefined functions.
- if (!Config->Relocatable)
+ // Handle the `--undefined <sym>` options.
+ for (auto *Arg : Args.filtered(OPT_undefined))
+ handleUndefined(Arg->getValue());
+
+ if (!Config->Relocatable) {
+ // Add synthetic dummies for weak undefined functions.
handleWeakUndefines();
+ if (!Config->Entry.empty()) {
+ EntrySym = handleUndefined(Config->Entry);
+ if (!EntrySym)
+ error("entry symbol not defined (pass --no-entry to supress): " +
+ Config->Entry);
+ }
+
+ // Make sure we have resolved all symbols.
+ if (!Config->AllowUndefined)
+ Symtab->reportRemainingUndefines();
+ }
+
+ if (errorCount())
+ return;
+
// Handle --export.
for (auto *Arg : Args.filtered(OPT_export)) {
StringRef Name = Arg->getValue();
@@ -504,27 +519,6 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
if (errorCount())
return;
- // Make sure we have resolved all symbols.
- if (!Config->Relocatable && !Config->AllowUndefined) {
- Symtab->reportRemainingUndefines();
- } else {
- // Even when using --allow-undefined we still want to report the absence of
- // our initial set of undefined symbols (i.e. the entry point and symbols
- // specified via --undefined).
- // Part of the reason for this is that these function don't have signatures
- // so which means they cannot be written as wasm function imports.
- for (auto *Arg : Args.filtered(OPT_undefined)) {
- Symbol *Sym = Symtab->find(Arg->getValue());
- if (!Sym->isDefined())
- error("symbol forced with --undefined not found: " + Sym->getName());
- }
- if (EntrySym && !EntrySym->isDefined())
- error("entry symbol not defined (pass --no-entry to supress): " +
- EntrySym->getName());
- }
- if (errorCount())
- return;
-
if (EntrySym)
EntrySym->setHidden(false);
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index 13a3c6fdddb..2a4249e3307 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -60,7 +60,6 @@ void SymbolTable::addCombinedLTOObject() {
}
void SymbolTable::reportRemainingUndefines() {
- SetVector<Symbol *> Undefs;
for (Symbol *Sym : SymVector) {
if (!Sym->isUndefined() || Sym->isWeak())
continue;
@@ -68,20 +67,8 @@ void SymbolTable::reportRemainingUndefines() {
continue;
if (!Sym->IsUsedInRegularObj)
continue;
- Undefs.insert(Sym);
+ error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym));
}
-
- if (Undefs.empty())
- return;
-
- for (ObjFile *File : ObjectFiles)
- for (Symbol *Sym : File->getSymbols())
- if (Undefs.count(Sym))
- error(toString(File) + ": undefined symbol: " + toString(*Sym));
-
- for (Symbol *Sym : Undefs)
- if (!Sym->getFile())
- error("undefined symbol: " + toString(*Sym));
}
Symbol *SymbolTable::find(StringRef Name) {
OpenPOWER on IntegriCloud