Index: include/llvm/BinaryFormat/Wasm.h =================================================================== --- include/llvm/BinaryFormat/Wasm.h +++ include/llvm/BinaryFormat/Wasm.h @@ -170,7 +170,8 @@ StringRef Name; uint8_t Kind; uint32_t Flags; - StringRef Module; // For undefined symbols the module name of the import + StringRef ImportModule; // For undefined symbols the module of the import + StringRef ImportName; // For undefined symbols the name of the import union { // For function or global symbols, the index in function or global index // space. @@ -289,6 +290,7 @@ const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; const unsigned WASM_SYMBOL_UNDEFINED = 0x10; +const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x20; #define WASM_RELOC(name, value) name = value, Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -988,7 +988,8 @@ case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_EVENT: encodeULEB128(Sym.ElementIndex, W.OS); - if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) + if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 || + (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) writeString(Sym.Name); break; case wasm::WASM_SYMBOL_TYPE_DATA: @@ -1460,6 +1461,8 @@ Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL; if (WS.isUndefined()) Flags |= wasm::WASM_SYMBOL_UNDEFINED; + if (WS.getName() != WS.getImportName()) + Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME; wasm::WasmSymbolInfo Info; Info.Name = WS.getName(); Index: lib/Object/WasmObjectFile.cpp =================================================================== --- lib/Object/WasmObjectFile.cpp +++ lib/Object/WasmObjectFile.cpp @@ -505,9 +505,13 @@ Function.SymbolName = Info.Name; } else { wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + Info.Name = readString(Ctx); + else + Info.Name = Import.Field; Signature = &Signatures[Import.SigIndex]; - Info.Name = Import.Field; - Info.Module = Import.Module; + Info.ImportName = Import.Field; + Info.ImportModule = Import.Module; } break; @@ -530,8 +534,13 @@ Global.SymbolName = Info.Name; } else { wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; - Info.Name = Import.Field; + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + Info.Name = readString(Ctx); + else + Info.Name = Import.Field; GlobalType = &Import.Global; + Info.ImportName = Import.Field; + Info.ImportModule = Import.Module; } break; @@ -585,9 +594,14 @@ } else { wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex]; + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + Info.Name = readString(Ctx); + else + Info.Name = Import.Field; EventType = &Import.Event; Signature = &Signatures[EventType->SigIndex]; - Info.Name = Import.Field; + Info.ImportName = Import.Field; + Info.ImportModule = Import.Module; } break; } Index: test/MC/WebAssembly/import-module.ll =================================================================== --- test/MC/WebAssembly/import-module.ll +++ test/MC/WebAssembly/import-module.ll @@ -0,0 +1,80 @@ +; RUN: llc -filetype=obj %s -o - | obj2yaml | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define void @test() { + call void @foo() + call void @plain() + ret void +} + +declare void @foo() #0 +declare void @plain() + +attributes #0 = { "wasm-import-module"="bar" "wasm-import-name"="qux" } + +; CHECK: --- !WASM +; CHECK: FileHeader: +; CHECK: Version: 0x00000001 +; CHECK: Sections: +; CHECK: - Type: TYPE +; CHECK: Signatures: +; CHECK: - Index: 0 +; CHECK: ReturnType: NORESULT +; CHECK: ParamTypes: [] +; CHECK: - Type: IMPORT +; CHECK: Imports: +; CHECK: - Module: env +; CHECK: Field: __linear_memory +; CHECK: Kind: MEMORY +; CHECK: Memory: +; CHECK: Initial: 0x00000000 +; CHECK: - Module: env +; CHECK: Field: __indirect_function_table +; CHECK: Kind: TABLE +; CHECK: Table: +; CHECK: ElemType: FUNCREF +; CHECK: Limits: +; CHECK: Initial: 0x00000000 +; CHECK: - Module: bar +; CHECK: Field: qux +; CHECK: Kind: FUNCTION +; CHECK: SigIndex: 0 +; CHECK: - Module: env +; CHECK: Field: plain +; CHECK: Kind: FUNCTION +; CHECK: SigIndex: 0 +; CHECK: - Type: FUNCTION +; CHECK: FunctionTypes: [ 0 ] +; CHECK: - Type: CODE +; CHECK: Relocations: +; CHECK: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB +; CHECK: Index: 1 +; CHECK: Offset: 0x00000004 +; CHECK: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB +; CHECK: Index: 2 +; CHECK: Offset: 0x0000000A +; CHECK: Functions: +; CHECK: - Index: 2 +; CHECK: Locals: [] +; CHECK: Body: 1080808080001081808080000B +; CHECK: - Type: CUSTOM +; CHECK: Name: linking +; CHECK: Version: 2 +; CHECK: SymbolTable: +; CHECK: - Index: 0 +; CHECK: Kind: FUNCTION +; CHECK: Name: test +; CHECK: Flags: [ ] +; CHECK: Function: 2 +; CHECK: - Index: 1 +; CHECK: Kind: FUNCTION +; CHECK: Name: foo +; CHECK: Flags: [ UNDEFINED ] +; CHECK: Function: 0 +; CHECK: - Index: 2 +; CHECK: Kind: FUNCTION +; CHECK: Name: plain +; CHECK: Flags: [ UNDEFINED ] +; CHECK: Function: 1 +; CHECK: ... Index: tools/lld/test/wasm/import-names.ll =================================================================== --- tools/lld/test/wasm/import-names.ll +++ tools/lld/test/wasm/import-names.ll @@ -0,0 +1,94 @@ +; 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: --- !WASM +; CHECK: FileHeader: +; CHECK: Version: 0x00000001 +; CHECK: Sections: +; CHECK: - Type: TYPE +; CHECK: Signatures: +; CHECK: - Index: 0 +; CHECK: ReturnType: NORESULT +; CHECK: ParamTypes: [] +; CHECK: - Type: IMPORT +; CHECK: Imports: +; CHECK: - Module: somewhere +; CHECK: Field: something +; CHECK: Kind: FUNCTION +; CHECK: SigIndex: 0 +; CHECK: - Type: FUNCTION +; CHECK: FunctionTypes: [ 0, 0 ] +; CHECK: - Type: TABLE +; CHECK: Tables: +; CHECK: - ElemType: FUNCREF +; CHECK: Limits: +; CHECK: Flags: [ HAS_MAX ] +; CHECK: Initial: 0x00000001 +; CHECK: Maximum: 0x00000001 +; CHECK: - Type: MEMORY +; CHECK: Memories: +; CHECK: - Initial: 0x00000002 +; CHECK: - Type: GLOBAL +; CHECK: Globals: +; CHECK: - Index: 0 +; CHECK: Type: I32 +; CHECK: Mutable: true +; CHECK: InitExpr: +; CHECK: Opcode: I32_CONST +; CHECK: Value: 66560 +; CHECK: - Index: 1 +; CHECK: Type: I32 +; CHECK: Mutable: false +; CHECK: InitExpr: +; CHECK: Opcode: I32_CONST +; CHECK: Value: 66560 +; CHECK: - Index: 2 +; CHECK: Type: I32 +; CHECK: Mutable: false +; CHECK: InitExpr: +; CHECK: Opcode: I32_CONST +; CHECK: Value: 1024 +; CHECK: - Type: EXPORT +; CHECK: Exports: +; CHECK: - Name: memory +; CHECK: Kind: MEMORY +; CHECK: Index: 0 +; CHECK: - Name: __heap_base +; CHECK: Kind: GLOBAL +; CHECK: Index: 1 +; CHECK: - Name: __data_end +; CHECK: Kind: GLOBAL +; CHECK: Index: 2 +; CHECK: - Name: _start +; CHECK: Kind: FUNCTION +; CHECK: Index: 2 +; CHECK: - Type: CODE +; CHECK: Functions: +; CHECK: - Index: 1 +; CHECK: Locals: [] +; CHECK: Body: 0B +; CHECK: - Index: 2 +; CHECK: Locals: [] +; CHECK: Body: 1080808080000B +; CHECK: - Type: CUSTOM +; CHECK: Name: name +; CHECK: FunctionNames: +; CHECK: - Index: 0 +; CHECK: Name: f0 +; CHECK: - Index: 1 +; CHECK: Name: __wasm_call_ctors +; CHECK: - Index: 2 +; CHECK: Name: _start +; CHECK: ... Index: tools/lld/wasm/InputFiles.cpp =================================================================== --- tools/lld/wasm/InputFiles.cpp +++ tools/lld/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, kDefaultModule, Flags, &F, nullptr); + return Symtab->addUndefinedFunction(Name, Name, kDefaultModule, Flags, &F, + nullptr); return Symtab->addUndefinedData(Name, Flags, &F); } Index: tools/lld/wasm/LTO.cpp =================================================================== --- tools/lld/wasm/LTO.cpp +++ tools/lld/wasm/LTO.cpp @@ -80,7 +80,8 @@ static void undefine(Symbol *S) { if (auto F = dyn_cast(S)) - replaceSymbol(F, F->getName(), kDefaultModule, 0, + replaceSymbol(F, F->getName(), F->getName(), + kDefaultModule, 0, F->getFile(), F->Signature); else if (isa(S)) replaceSymbol(S, S->getName(), 0, S->getFile()); Index: tools/lld/wasm/SymbolTable.h =================================================================== --- tools/lld/wasm/SymbolTable.h +++ tools/lld/wasm/SymbolTable.h @@ -58,11 +58,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); Index: tools/lld/wasm/SymbolTable.cpp =================================================================== --- tools/lld/wasm/SymbolTable.cpp +++ tools/lld/wasm/SymbolTable.cpp @@ -315,7 +315,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 << @@ -326,7 +327,8 @@ std::tie(S, WasInserted) = insert(Name, File); if (WasInserted) - replaceSymbol(S, Name, Module, Flags, File, Sig); + replaceSymbol(S, Name, ImportName, ImportModule, Flags, + File, Sig); else if (auto *Lazy = dyn_cast(S)) Lazy->fetch(); else @@ -352,7 +354,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"); @@ -362,7 +365,8 @@ std::tie(S, WasInserted) = insert(Name, File); if (WasInserted) - replaceSymbol(S, Name, Flags, File, Type); + replaceSymbol(S, Name, ImportName, ImportModule, Flags, + File, Type); else if (auto *Lazy = dyn_cast(S)) Lazy->fetch(); else if (S->isDefined()) Index: tools/lld/wasm/Symbols.h =================================================================== --- tools/lld/wasm/Symbols.h +++ tools/lld/wasm/Symbols.h @@ -155,17 +155,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 { @@ -271,13 +273,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 Index: tools/lld/wasm/Writer.cpp =================================================================== --- tools/lld/wasm/Writer.cpp +++ tools/lld/wasm/Writer.cpp @@ -184,12 +184,17 @@ for (const Symbol *Sym : ImportedSymbols) { WasmImport Import; - if (auto *F = dyn_cast(Sym)) - Import.Module = F->Module; - else + if (auto *F = dyn_cast(Sym)) { + Import.Field = F->ImportName; + Import.Module = F->ImportModule; + } else if (auto *G = dyn_cast(Sym)) { + Import.Field = G->ImportName; + Import.Module = G->ImportModule; + } else { + Import.Field = Sym->getName(); Import.Module = kDefaultModule; + } - Import.Field = Sym->getName(); if (auto *FunctionSym = dyn_cast(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(Sym)) { + if (F->getName() != F->ImportName) + Flags |= WASM_SYMBOL_EXPLICIT_NAME; + } else if (auto *G = dyn_cast(Sym)) { + if (G->getName() != G->ImportName) + Flags |= WASM_SYMBOL_EXPLICIT_NAME; + } return Flags; } @@ -513,15 +525,18 @@ if (auto *F = dyn_cast(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(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(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(Sym)) { writeStr(Sub.OS, Sym->getName(), "sym name"); Index: tools/yaml2obj/yaml2wasm.cpp =================================================================== --- tools/yaml2obj/yaml2wasm.cpp +++ tools/yaml2obj/yaml2wasm.cpp @@ -172,7 +172,8 @@ case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_EVENT: encodeULEB128(Info.ElementIndex, SubSection.GetStream()); - if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) + if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 || + (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) writeStringRef(Info.Name, SubSection.GetStream()); break; case wasm::WASM_SYMBOL_TYPE_DATA: