[lld] r375081 - [lld][WebAssebmly] Preserve custom import attributes with LTO

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 16 22:16:55 PDT 2019


Author: sbc
Date: Wed Oct 16 22:16:54 2019
New Revision: 375081

URL: http://llvm.org/viewvc/llvm-project?rev=375081&view=rev
Log:
[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

Added:
    lld/trunk/test/wasm/Inputs/import-attributes.ll
    lld/trunk/test/wasm/import-attribute-mismatch.ll
    lld/trunk/test/wasm/lto/import-attributes.ll
Modified:
    lld/trunk/wasm/InputFiles.cpp
    lld/trunk/wasm/LTO.cpp
    lld/trunk/wasm/SymbolTable.cpp

Added: lld/trunk/test/wasm/Inputs/import-attributes.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/import-attributes.ll?rev=375081&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/import-attributes.ll (added)
+++ lld/trunk/test/wasm/Inputs/import-attributes.ll Wed Oct 16 22:16:54 2019
@@ -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" }

Added: lld/trunk/test/wasm/import-attribute-mismatch.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/import-attribute-mismatch.ll?rev=375081&view=auto
==============================================================================
--- lld/trunk/test/wasm/import-attribute-mismatch.ll (added)
+++ lld/trunk/test/wasm/import-attribute-mismatch.ll Wed Oct 16 22:16:54 2019
@@ -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

Added: lld/trunk/test/wasm/lto/import-attributes.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/lto/import-attributes.ll?rev=375081&view=auto
==============================================================================
--- lld/trunk/test/wasm/lto/import-attributes.ll (added)
+++ lld/trunk/test/wasm/lto/import-attributes.ll Wed Oct 16 22:16:54 2019
@@ -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

Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=375081&r1=375080&r2=375081&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Wed Oct 16 22:16:54 2019
@@ -527,8 +527,8 @@ static Symbol *createBitcodeSymbol(const
   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);
   }
 

Modified: lld/trunk/wasm/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/LTO.cpp?rev=375081&r1=375080&r2=375081&view=diff
==============================================================================
--- lld/trunk/wasm/LTO.cpp (original)
+++ lld/trunk/wasm/LTO.cpp Wed Oct 16 22:16:54 2019
@@ -77,9 +77,8 @@ BitcodeCompiler::~BitcodeCompiler() = de
 
 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

Modified: lld/trunk/wasm/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.cpp?rev=375081&r1=375080&r2=375081&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.cpp (original)
+++ lld/trunk/wasm/SymbolTable.cpp Wed Oct 16 22:16:54 2019
@@ -393,6 +393,36 @@ Symbol *SymbolTable::addDefinedEvent(Str
   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::addUndefinedFunctio
       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::addUndefinedFunctio
       else if (getFunctionVariant(s, sig, file, &s))
         replaceSym();
     }
+    if (existingUndefined)
+      setImportAttributes(existingUndefined, importName, importModule, file);
   }
 
   return s;




More information about the llvm-commits mailing list