summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2019-10-17 05:16:54 +0000
committerSam Clegg <sbc@chromium.org>2019-10-17 05:16:54 +0000
commit67b055841f3b64efd1e92bde3ed7aeeb493c1182 (patch)
tree049728a5c29e7bc5910888b0c5b895416b3f0f2c
parent9e7e36d4c2602ed10fc1ac037c7ebed50b7df859 (diff)
downloadbcm5719-llvm-67b055841f3b64efd1e92bde3ed7aeeb493c1182.tar.gz
bcm5719-llvm-67b055841f3b64efd1e92bde3ed7aeeb493c1182.zip
[lld][WebAssebmly] Preserve custom import attributes with LTO
Undefined symbols in WebAssembly can come with custom `import-module` and `import-field` attributes. However when reading symbols from bitcode object files during LTO those curtom attributes are not available. Once we compile the LTO object and read in the symbol table from the object file we have access to these custom attributes. In this case, when undefined symbols are added and a symbol already exists in the SymbolTable we can't simple return it, we may need to update the symbol's attributes. Fixes: PR43211 Differential Revision: https://reviews.llvm.org/D68959 llvm-svn: 375081
-rw-r--r--lld/test/wasm/Inputs/import-attributes.ll10
-rw-r--r--lld/test/wasm/import-attribute-mismatch.ll18
-rw-r--r--lld/test/wasm/lto/import-attributes.ll22
-rw-r--r--lld/wasm/InputFiles.cpp4
-rw-r--r--lld/wasm/LTO.cpp5
-rw-r--r--lld/wasm/SymbolTable.cpp34
6 files changed, 87 insertions, 6 deletions
diff --git a/lld/test/wasm/Inputs/import-attributes.ll b/lld/test/wasm/Inputs/import-attributes.ll
new file mode 100644
index 00000000000..27ee2774f22
--- /dev/null
+++ b/lld/test/wasm/Inputs/import-attributes.ll
@@ -0,0 +1,10 @@
+target triple = "wasm32-unknown-unknown"
+
+define void @call_foo() {
+ call void @foo();
+ ret void
+}
+
+declare void @foo() #0
+
+attributes #0 = { "wasm-import-module"="baz" }
diff --git a/lld/test/wasm/import-attribute-mismatch.ll b/lld/test/wasm/import-attribute-mismatch.ll
new file mode 100644
index 00000000000..d3ba294a212
--- /dev/null
+++ b/lld/test/wasm/import-attribute-mismatch.ll
@@ -0,0 +1,18 @@
+; RUN: llc -filetype=obj %s -o %t1.o
+; RUN: llc -filetype=obj %S/Inputs/import-attributes.ll -o %t2.o
+; RUN: not wasm-ld --export call_foo --allow-undefined -o %t.wasm %t1.o %t2.o 2>&1 | FileCheck %s
+
+target triple = "wasm32-unknown-unknown-wasm"
+
+define void @_start() {
+ call void @foo();
+ ret void
+}
+
+declare void @foo() #0
+
+attributes #0 = { "wasm-import-module"="bar" }
+
+; CHECK: wasm-ld: error: import module mismatch for symbol: foo
+; CHECK: >>> defined as bar in {{.*}}1.o
+; CHECK: >>> defined as baz in {{.*}}2.o
diff --git a/lld/test/wasm/lto/import-attributes.ll b/lld/test/wasm/lto/import-attributes.ll
new file mode 100644
index 00000000000..afbb8e15c00
--- /dev/null
+++ b/lld/test/wasm/lto/import-attributes.ll
@@ -0,0 +1,22 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: wasm-ld --allow-undefined -o %t.wasm %t.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target triple = "wasm32-unknown-unknown-wasm"
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+
+define void @_start() {
+ call void @foo();
+ ret void
+}
+
+declare void @foo() #0
+
+attributes #0 = { "wasm-import-module"="bar" "wasm-import-name"="customfoo" }
+
+; CHECK: - Type: IMPORT
+; CHECK-NEXT: Imports:
+; CHECK-NEXT: - Module: bar
+; CHECK-NEXT: Field: customfoo
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: SigIndex: 0
diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index 13e066e8669..74308ff6655 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -527,8 +527,8 @@ static Symbol *createBitcodeSymbol(const std::vector<bool> &keptComdats,
if (objSym.isUndefined() || excludedByComdat) {
flags |= WASM_SYMBOL_UNDEFINED;
if (objSym.isExecutable())
- return symtab->addUndefinedFunction(name, name, defaultModule, flags, &f,
- nullptr, true);
+ return symtab->addUndefinedFunction(name, "", "", flags, &f, nullptr,
+ true);
return symtab->addUndefinedData(name, flags, &f);
}
diff --git a/lld/wasm/LTO.cpp b/lld/wasm/LTO.cpp
index de234365dab..615b4c9dc94 100644
--- a/lld/wasm/LTO.cpp
+++ b/lld/wasm/LTO.cpp
@@ -77,9 +77,8 @@ BitcodeCompiler::~BitcodeCompiler() = default;
static void undefine(Symbol *s) {
if (auto f = dyn_cast<DefinedFunction>(s))
- replaceSymbol<UndefinedFunction>(f, f->getName(), f->getName(),
- defaultModule, 0,
- f->getFile(), f->signature);
+ replaceSymbol<UndefinedFunction>(f, f->getName(), "", "", 0, f->getFile(),
+ f->signature);
else if (isa<DefinedData>(s))
replaceSymbol<UndefinedData>(s, s->getName(), 0, s->getFile());
else
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index 92069eab54d..14616f961b6 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -393,6 +393,36 @@ Symbol *SymbolTable::addDefinedEvent(StringRef name, uint32_t flags,
return s;
}
+// This function get called when an undefined symbol is added, and there is
+// already an existing one in the symbols table. In this case we check that
+// custom 'import-module' and 'import-field' symbol attributes agree.
+// With LTO these attributes are not avialable when the bitcode is read and only
+// become available when the LTO object is read. In this case we silently
+// replace the empty attributes with the valid ones.
+template <typename T>
+static void setImportAttributes(T *existing, StringRef importName,
+ StringRef importModule, InputFile *file) {
+ if (!importName.empty()) {
+ if (existing->importName.empty())
+ existing->importName = importName;
+ if (existing->importName != importName)
+ error("import name mismatch for symbol: " + toString(*existing) +
+ "\n>>> defined as " + existing->importName + " in " +
+ toString(existing->getFile()) + "\n>>> defined as " + importName +
+ " in " + toString(file));
+ }
+
+ if (!importModule.empty()) {
+ if (existing->importModule.empty())
+ existing->importModule = importModule;
+ if (existing->importModule != importModule)
+ error("import module mismatch for symbol: " + toString(*existing) +
+ "\n>>> defined as " + existing->importModule + " in " +
+ toString(existing->getFile()) + "\n>>> defined as " + importModule +
+ " in " + toString(file));
+ }
+}
+
Symbol *SymbolTable::addUndefinedFunction(StringRef name, StringRef importName,
StringRef importModule,
uint32_t flags, InputFile *file,
@@ -424,10 +454,10 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name, StringRef importName,
reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION);
return s;
}
+ auto *existingUndefined = dyn_cast<UndefinedFunction>(existingFunction);
if (!existingFunction->signature && sig)
existingFunction->signature = sig;
if (isCalledDirectly && !signatureMatches(existingFunction, sig)) {
- auto* existingUndefined = dyn_cast<UndefinedFunction>(existingFunction);
// If the existing undefined functions is not called direcltly then let
// this one take precedence. Otherwise the existing function is either
// direclty called or defined, in which case we need a function variant.
@@ -436,6 +466,8 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name, StringRef importName,
else if (getFunctionVariant(s, sig, file, &s))
replaceSym();
}
+ if (existingUndefined)
+ setImportAttributes(existingUndefined, importName, importModule, file);
}
return s;
OpenPOWER on IntegriCloud