summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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