summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2018-08-04 00:04:06 +0000
committerSam Clegg <sbc@chromium.org>2018-08-04 00:04:06 +0000
commit47e2b6b29eae57267b5c966eb7d02dc8eae0caaf (patch)
tree457d8d54ec7090c29e0acbeaf5f778192946046c
parentefab30c73ee9793c780665fbd46a68aa5ac2a138 (diff)
downloadbcm5719-llvm-47e2b6b29eae57267b5c966eb7d02dc8eae0caaf.tar.gz
bcm5719-llvm-47e2b6b29eae57267b5c966eb7d02dc8eae0caaf.zip
[WebAssembly] Don't error when --undefined symbols are not found
This matches the behavior of the ELF linker where -u/--undefined means symbols will get pulled in from archives but won't result in link error if they are missing. Also, don't actually great symbol table entries for the undefined symbols, again matching more closely the ELF linker. This also results in simplification of the code. Differential Revision: https://reviews.llvm.org/D50279 llvm-svn: 338938
-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