[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.

This is the MC/Object portion of the patch.

Differential Revision: https://reviews.llvm.org/D57632

llvm-svn: 353474
This commit is contained in:
Dan Gohman 2019-02-07 22:03:32 +00:00
parent 9b84eeaa3e
commit 29874cea31
7 changed files with 64 additions and 10 deletions

View File

@ -170,7 +170,8 @@ struct WasmSymbolInfo {
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.
@ -290,6 +291,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_EXPORTED = 0x20;
const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40;
#define WASM_RELOC(name, value) name = value,

View File

@ -982,7 +982,8 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
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:
@ -1456,6 +1457,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
Flags |= wasm::WASM_SYMBOL_UNDEFINED;
if (WS.isExported())
Flags |= wasm::WASM_SYMBOL_EXPORTED;
if (WS.getName() != WS.getImportName())
Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
wasm::WasmSymbolInfo Info;
Info.Name = WS.getName();

View File

@ -505,9 +505,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Function.SymbolName = Info.Name;
} else {
wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
Signature = &Signatures[Import.SigIndex];
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
Info.Name = readString(Ctx);
else
Info.Name = Import.Field;
Info.Module = Import.Module;
Signature = &Signatures[Import.SigIndex];
Info.ImportName = Import.Field;
Info.ImportModule = Import.Module;
}
break;
@ -530,8 +534,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Global.SymbolName = Info.Name;
} else {
wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
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 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
} 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;
}

View File

@ -186,7 +186,8 @@
; CHECK-NEXT: Flags [ (0x10)
; CHECK-NEXT: UNDEFINED (0x10)
; CHECK-NEXT: ]
; CHECK-NEXT: Module:
; CHECK-NEXT: ImportName:
; CHECK-NEXT: ImportModule:
; CHECK-NEXT: }
; CHECK-NEXT: Symbol {
; CHECK-NEXT: Name: ptr2

View File

@ -0,0 +1,31 @@
; 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: - Type: IMPORT
; CHECK-NEXT: Imports:
; CHECK: - Module: bar
; CHECK-NEXT: Field: qux
; CHECK-NEXT: Kind: FUNCTION
; CHECK: - Module: env
; CHECK-NEXT: Field: plain
; CHECK-NEXT: Kind: FUNCTION
; CHECK: - Type: CUSTOM
; CHECK: Name: foo
; CHECK-NEXT: Flags: [ UNDEFINED ]
; CHECK: Name: plain
; CHECK-NEXT: Flags: [ UNDEFINED ]

View File

@ -224,8 +224,10 @@ void WasmDumper::printSymbol(const SymbolRef &Sym) {
W.printEnum("Type", Symbol.Info.Kind, makeArrayRef(WasmSymbolTypes));
W.printFlags("Flags", Symbol.Info.Flags, makeArrayRef(WasmSymbolFlags));
if (Symbol.Info.Flags & wasm::WASM_SYMBOL_UNDEFINED)
W.printString("Module", Symbol.Info.Module);
if (Symbol.Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) {
W.printString("ImportName", Symbol.Info.ImportName);
W.printString("ImportModule", Symbol.Info.ImportModule);
}
if (Symbol.Info.Kind != wasm::WASM_SYMBOL_TYPE_DATA) {
W.printHex("ElementIndex", Symbol.Info.ElementIndex);
} else if (!(Symbol.Info.Flags & wasm::WASM_SYMBOL_UNDEFINED)) {

View File

@ -172,7 +172,8 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
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: