[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

llvm-svn: 353473
This commit is contained in:
Dan Gohman 2019-02-07 22:00:48 +00:00
parent 166c262f23
commit 9b84eeaa3e
8 changed files with 86 additions and 24 deletions

View File

@ -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

View File

@ -443,7 +443,9 @@ static Symbol *handleUndefined(StringRef Name) {
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;

View File

@ -378,12 +378,15 @@ Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
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 @@ static Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &ObjSym,
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);
}

View File

@ -80,7 +80,8 @@ BitcodeCompiler::~BitcodeCompiler() = default;
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());

View File

@ -338,7 +338,8 @@ Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags,
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 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef Module,
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 @@ Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags,
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 @@ Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags,
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())

View File

@ -61,11 +61,13 @@ public:
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);

View File

@ -159,17 +159,19 @@ public:
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 @@ public:
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

View File

@ -184,12 +184,17 @@ void Writer::createImportSection() {
for (const Symbol *Sym : ImportedSymbols) {
WasmImport Import;
if (auto *F = dyn_cast<UndefinedFunction>(Sym))
Import.Module = F->Module;
else
Import.Module = DefaultModule;
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;
}
if (auto *FunctionSym = dyn_cast<FunctionSymbol>(Sym)) {
Import.Kind = WASM_EXTERNAL_FUNCTION;
Import.SigIndex = lookupType(*FunctionSym->Signature);
@ -448,6 +453,13 @@ static uint32_t getWasmFlags(const Symbol *Sym) {
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 @@ void Writer::createLinkingSection() {
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");