[WebAssembly] Fix imported function symbol names that differ from their import names in the .o format
Add a flag to allow symbols to have a wasm import name which differs from the
linker symbol name, allowing the linker to link code using the import_module
attribute.
Differential Revision: https://reviews.llvm.org/D57632
git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@353473 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/wasm/import-names.ll b/test/wasm/import-names.ll
new file mode 100644
index 0000000..a3953d3
--- /dev/null
+++ b/test/wasm/import-names.ll
@@ -0,0 +1,27 @@
+; RUN: llc -filetype=obj %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"
+
+declare void @f0() #0
+
+define void @_start() {
+ call void @f0()
+ ret void
+}
+
+attributes #0 = { "wasm-import-module"="somewhere" "wasm-import-name"="something" }
+
+; CHECK: - Type: IMPORT
+; CHECK-NEXT: Imports:
+; CHECK-NEXT: - Module: somewhere
+; CHECK-NEXT: Field: something
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: SigIndex: 0
+
+; CHECK: - Type: CUSTOM
+; CHECK-NEXT: Name: name
+; CHECK-NEXT: FunctionNames:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: f0
diff --git a/wasm/Driver.cpp b/wasm/Driver.cpp
index 396f30a..b866cb2 100644
--- a/wasm/Driver.cpp
+++ b/wasm/Driver.cpp
@@ -443,7 +443,9 @@
static UndefinedGlobal *
createUndefinedGlobal(StringRef Name, llvm::wasm::WasmGlobalType *Type) {
auto *Sym =
- cast<UndefinedGlobal>(Symtab->addUndefinedGlobal(Name, 0, nullptr, Type));
+ cast<UndefinedGlobal>(Symtab->addUndefinedGlobal(Name, Name,
+ DefaultModule, 0,
+ nullptr, Type));
Config->AllowUndefinedSymbols.insert(Sym->getName());
Sym->IsUsedInRegularObj = true;
return Sym;
diff --git a/wasm/InputFiles.cpp b/wasm/InputFiles.cpp
index 2c6a316..2a5c10e 100644
--- a/wasm/InputFiles.cpp
+++ b/wasm/InputFiles.cpp
@@ -378,12 +378,15 @@
switch (Sym.Info.Kind) {
case WASM_SYMBOL_TYPE_FUNCTION:
- return Symtab->addUndefinedFunction(Name, Sym.Info.Module, Flags, this,
+ return Symtab->addUndefinedFunction(Name, Sym.Info.ImportName,
+ Sym.Info.ImportModule, Flags, this,
Sym.Signature);
case WASM_SYMBOL_TYPE_DATA:
return Symtab->addUndefinedData(Name, Flags, this);
case WASM_SYMBOL_TYPE_GLOBAL:
- return Symtab->addUndefinedGlobal(Name, Flags, this, Sym.GlobalType);
+ return Symtab->addUndefinedGlobal(Name, Sym.Info.ImportName,
+ Sym.Info.ImportModule, Flags, this,
+ Sym.GlobalType);
case WASM_SYMBOL_TYPE_SECTION:
llvm_unreachable("section symbols cannot be undefined");
}
@@ -447,7 +450,8 @@
if (ObjSym.isUndefined()) {
if (ObjSym.isExecutable())
- return Symtab->addUndefinedFunction(Name, DefaultModule, Flags, &F, nullptr);
+ return Symtab->addUndefinedFunction(Name, Name, DefaultModule, Flags, &F,
+ nullptr);
return Symtab->addUndefinedData(Name, Flags, &F);
}
diff --git a/wasm/LTO.cpp b/wasm/LTO.cpp
index e19a831..19b23d5 100644
--- a/wasm/LTO.cpp
+++ b/wasm/LTO.cpp
@@ -80,7 +80,8 @@
static void undefine(Symbol *S) {
if (auto F = dyn_cast<DefinedFunction>(S))
- replaceSymbol<UndefinedFunction>(F, F->getName(), DefaultModule, 0,
+ replaceSymbol<UndefinedFunction>(F, F->getName(), F->getName(),
+ DefaultModule, 0,
F->getFile(), F->Signature);
else if (isa<DefinedData>(S))
replaceSymbol<UndefinedData>(S, S->getName(), 0, S->getFile());
diff --git a/wasm/SymbolTable.cpp b/wasm/SymbolTable.cpp
index 79e85d5..00ee88f 100644
--- a/wasm/SymbolTable.cpp
+++ b/wasm/SymbolTable.cpp
@@ -338,7 +338,8 @@
return S;
}
-Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef Module,
+Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName,
+ StringRef ImportModule,
uint32_t Flags, InputFile *File,
const WasmSignature *Sig) {
LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name <<
@@ -349,7 +350,8 @@
std::tie(S, WasInserted) = insert(Name, File);
if (WasInserted)
- replaceSymbol<UndefinedFunction>(S, Name, Module, Flags, File, Sig);
+ replaceSymbol<UndefinedFunction>(S, Name, ImportName, ImportModule, Flags,
+ File, Sig);
else if (auto *Lazy = dyn_cast<LazySymbol>(S))
Lazy->fetch();
else
@@ -375,7 +377,8 @@
return S;
}
-Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags,
+Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, StringRef ImportName,
+ StringRef ImportModule, uint32_t Flags,
InputFile *File,
const WasmGlobalType *Type) {
LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n");
@@ -385,7 +388,8 @@
std::tie(S, WasInserted) = insert(Name, File);
if (WasInserted)
- replaceSymbol<UndefinedGlobal>(S, Name, Flags, File, Type);
+ replaceSymbol<UndefinedGlobal>(S, Name, ImportName, ImportModule, Flags,
+ File, Type);
else if (auto *Lazy = dyn_cast<LazySymbol>(S))
Lazy->fetch();
else if (S->isDefined())
diff --git a/wasm/SymbolTable.h b/wasm/SymbolTable.h
index ed5c0ca..67133ce 100644
--- a/wasm/SymbolTable.h
+++ b/wasm/SymbolTable.h
@@ -61,11 +61,13 @@
Symbol *addDefinedEvent(StringRef Name, uint32_t Flags, InputFile *File,
InputEvent *E);
- Symbol *addUndefinedFunction(StringRef Name, StringRef Module, uint32_t Flags,
+ Symbol *addUndefinedFunction(StringRef Name, StringRef ImportName,
+ StringRef ImportModule, uint32_t Flags,
InputFile *File, const WasmSignature *Signature);
Symbol *addUndefinedData(StringRef Name, uint32_t Flags, InputFile *File);
- Symbol *addUndefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File,
- const WasmGlobalType *Type);
+ Symbol *addUndefinedGlobal(StringRef Name, StringRef ImportName,
+ StringRef ImportModule, uint32_t Flags,
+ InputFile *File, const WasmGlobalType *Type);
void addLazy(ArchiveFile *F, const llvm::object::Archive::Symbol *Sym);
diff --git a/wasm/Symbols.h b/wasm/Symbols.h
index 535948c..d50f15f 100644
--- a/wasm/Symbols.h
+++ b/wasm/Symbols.h
@@ -159,17 +159,19 @@
class UndefinedFunction : public FunctionSymbol {
public:
- UndefinedFunction(StringRef Name, StringRef Module, uint32_t Flags,
+ UndefinedFunction(StringRef Name, StringRef ImportName,
+ StringRef ImportModule, uint32_t Flags,
InputFile *File = nullptr,
const WasmSignature *Type = nullptr)
: FunctionSymbol(Name, UndefinedFunctionKind, Flags, File, Type),
- Module(Module) {}
+ ImportName(ImportName), ImportModule(ImportModule) {}
static bool classof(const Symbol *S) {
return S->kind() == UndefinedFunctionKind;
}
- StringRef Module;
+ StringRef ImportName;
+ StringRef ImportModule;
};
class SectionSymbol : public Symbol {
@@ -275,13 +277,18 @@
class UndefinedGlobal : public GlobalSymbol {
public:
- UndefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File = nullptr,
+ UndefinedGlobal(StringRef Name, StringRef ImportName, StringRef ImportModule,
+ uint32_t Flags, InputFile *File = nullptr,
const WasmGlobalType *Type = nullptr)
- : GlobalSymbol(Name, UndefinedGlobalKind, Flags, File, Type) {}
+ : GlobalSymbol(Name, UndefinedGlobalKind, Flags, File, Type),
+ ImportName(ImportName), ImportModule(ImportModule) {}
static bool classof(const Symbol *S) {
return S->kind() == UndefinedGlobalKind;
}
+
+ StringRef ImportName;
+ StringRef ImportModule;
};
// Wasm events are features that suspend the current execution and transfer the
diff --git a/wasm/Writer.cpp b/wasm/Writer.cpp
index cb85332..213beca 100644
--- a/wasm/Writer.cpp
+++ b/wasm/Writer.cpp
@@ -184,12 +184,17 @@
for (const Symbol *Sym : ImportedSymbols) {
WasmImport Import;
- if (auto *F = dyn_cast<UndefinedFunction>(Sym))
- Import.Module = F->Module;
- else
+ if (auto *F = dyn_cast<UndefinedFunction>(Sym)) {
+ Import.Field = F->ImportName;
+ Import.Module = F->ImportModule;
+ } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) {
+ Import.Field = G->ImportName;
+ Import.Module = G->ImportModule;
+ } else {
+ Import.Field = Sym->getName();
Import.Module = DefaultModule;
+ }
- Import.Field = Sym->getName();
if (auto *FunctionSym = dyn_cast<FunctionSymbol>(Sym)) {
Import.Kind = WASM_EXTERNAL_FUNCTION;
Import.SigIndex = lookupType(*FunctionSym->Signature);
@@ -448,6 +453,13 @@
Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
if (Sym->isUndefined())
Flags |= WASM_SYMBOL_UNDEFINED;
+ if (auto *F = dyn_cast<UndefinedFunction>(Sym)) {
+ if (F->getName() != F->ImportName)
+ Flags |= WASM_SYMBOL_EXPLICIT_NAME;
+ } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) {
+ if (G->getName() != G->ImportName)
+ Flags |= WASM_SYMBOL_EXPLICIT_NAME;
+ }
return Flags;
}
@@ -513,15 +525,18 @@
if (auto *F = dyn_cast<FunctionSymbol>(Sym)) {
writeUleb128(Sub.OS, F->getFunctionIndex(), "index");
- if (Sym->isDefined())
+ if (Sym->isDefined() ||
+ (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
writeStr(Sub.OS, Sym->getName(), "sym name");
} else if (auto *G = dyn_cast<GlobalSymbol>(Sym)) {
writeUleb128(Sub.OS, G->getGlobalIndex(), "index");
- if (Sym->isDefined())
+ if (Sym->isDefined() ||
+ (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
writeStr(Sub.OS, Sym->getName(), "sym name");
} else if (auto *E = dyn_cast<EventSymbol>(Sym)) {
writeUleb128(Sub.OS, E->getEventIndex(), "index");
- if (Sym->isDefined())
+ if (Sym->isDefined() ||
+ (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
writeStr(Sub.OS, Sym->getName(), "sym name");
} else if (isa<DataSymbol>(Sym)) {
writeStr(Sub.OS, Sym->getName(), "sym name");