forked from OSchip/llvm-project
[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:
parent
166c262f23
commit
9b84eeaa3e
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue