[WebAssembly] Improve libObject support for wasm imports and exports

Previously we had only supported the importing and
exporting of functions and globals.

Also, add usefull overload of getWasmSymbol() and
getNumberOfSymbols() in support of lld port.

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

llvm-svn: 302601
This commit is contained in:
Sam Clegg 2017-05-09 23:48:41 +00:00
parent 78046e4624
commit 2ffff5af85
9 changed files with 171 additions and 76 deletions

View File

@ -67,7 +67,8 @@ public:
WasmObjectFile(MemoryBufferRef Object, Error &Err); WasmObjectFile(MemoryBufferRef Object, Error &Err);
const wasm::WasmObjectHeader &getHeader() const; const wasm::WasmObjectHeader &getHeader() const;
const WasmSymbol &getWasmSymbol(DataRefImpl Symb) const; const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const;
const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const;
const WasmSection &getWasmSection(const SectionRef &Section) const; const WasmSection &getWasmSection(const SectionRef &Section) const;
const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const; const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const;
@ -81,6 +82,10 @@ public:
const std::vector<wasm::WasmGlobal>& globals() const { return Globals; } const std::vector<wasm::WasmGlobal>& globals() const { return Globals; }
const std::vector<wasm::WasmExport>& exports() const { return Exports; } const std::vector<wasm::WasmExport>& exports() const { return Exports; }
uint32_t getNumberOfSymbols() const {
return Symbols.size();
}
const std::vector<wasm::WasmElemSegment>& elements() const { const std::vector<wasm::WasmElemSegment>& elements() const {
return ElemSegments; return ElemSegments;
} }

View File

@ -34,17 +34,6 @@ struct FileHeader {
yaml::Hex32 Version; yaml::Hex32 Version;
}; };
struct Import {
StringRef Module;
StringRef Field;
ExportKind Kind;
union {
uint32_t SigIndex;
ValueType GlobalType;
};
bool GlobalMutable;
};
struct Limits { struct Limits {
yaml::Hex32 Flags; yaml::Hex32 Flags;
yaml::Hex32 Initial; yaml::Hex32 Initial;
@ -74,6 +63,18 @@ struct Global {
wasm::WasmInitExpr InitExpr; wasm::WasmInitExpr InitExpr;
}; };
struct Import {
StringRef Module;
StringRef Field;
ExportKind Kind;
union {
uint32_t SigIndex;
Global Global;
Table Table;
Limits Memory;
};
};
struct LocalDecl { struct LocalDecl {
ValueType Type; ValueType Type;
uint32_t Count; uint32_t Count;

View File

@ -37,17 +37,6 @@ struct WasmSignature {
int32_t ReturnType; int32_t ReturnType;
}; };
struct WasmImport {
StringRef Module;
StringRef Field;
uint32_t Kind;
union {
uint32_t SigIndex;
int32_t GlobalType;
};
bool GlobalMutable;
};
struct WasmExport { struct WasmExport {
StringRef Name; StringRef Name;
uint32_t Kind; uint32_t Kind;
@ -82,6 +71,18 @@ struct WasmGlobal {
WasmInitExpr InitExpr; WasmInitExpr InitExpr;
}; };
struct WasmImport {
StringRef Module;
StringRef Field;
uint32_t Kind;
union {
uint32_t SigIndex;
WasmGlobal Global;
WasmTable Table;
WasmLimits Memory;
};
};
struct WasmLocalDecl { struct WasmLocalDecl {
int32_t Type; int32_t Type;
uint32_t Count; uint32_t Count;

View File

@ -168,6 +168,13 @@ static wasm::WasmLimits readLimits(const uint8_t *&Ptr) {
return Result; return Result;
} }
static wasm::WasmTable readTable(const uint8_t *&Ptr) {
wasm::WasmTable Table;
Table.ElemType = readVarint7(Ptr);
Table.Limits = readLimits(Ptr);
return Table;
}
static Error readSection(WasmSection &Section, const uint8_t *&Ptr, static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
const uint8_t *Start) { const uint8_t *Start) {
// TODO(sbc): Avoid reading past EOF in the case of malformed files. // TODO(sbc): Avoid reading past EOF in the case of malformed files.
@ -397,13 +404,22 @@ Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End)
Sections.size(), i); Sections.size(), i);
break; break;
case wasm::WASM_EXTERNAL_GLOBAL: case wasm::WASM_EXTERNAL_GLOBAL:
Im.GlobalType = readVarint7(Ptr); Im.Global.Type = readVarint7(Ptr);
Im.GlobalMutable = readVaruint1(Ptr); Im.Global.Mutable = readVaruint1(Ptr);
Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT, Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
Sections.size(), i); Sections.size(), i);
break; break;
case wasm::WASM_EXTERNAL_MEMORY:
Im.Memory = readLimits(Ptr);
break;
case wasm::WASM_EXTERNAL_TABLE:
Im.Table = readTable(Ptr);
if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) {
return make_error<GenericBinaryError>("Invalid table element type",
object_error::parse_failed);
}
break;
default: default:
// TODO(sbc): Handle other kinds of imports
return make_error<GenericBinaryError>( return make_error<GenericBinaryError>(
"Unexpected import kind", object_error::parse_failed); "Unexpected import kind", object_error::parse_failed);
} }
@ -431,14 +447,11 @@ Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End)
uint32_t Count = readVaruint32(Ptr); uint32_t Count = readVaruint32(Ptr);
Tables.reserve(Count); Tables.reserve(Count);
while (Count--) { while (Count--) {
wasm::WasmTable Table; Tables.push_back(readTable(Ptr));
Table.ElemType = readVarint7(Ptr); if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) {
if (Table.ElemType != wasm::WASM_TYPE_ANYFUNC) {
return make_error<GenericBinaryError>("Invalid table element type", return make_error<GenericBinaryError>("Invalid table element type",
object_error::parse_failed); object_error::parse_failed);
} }
Table.Limits = readLimits(Ptr);
Tables.push_back(Table);
} }
if (Ptr != End) if (Ptr != End)
return make_error<GenericBinaryError>("Table section ended prematurely", return make_error<GenericBinaryError>("Table section ended prematurely",
@ -493,8 +506,10 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT, Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT,
Sections.size(), i); Sections.size(), i);
break; break;
case wasm::WASM_EXTERNAL_MEMORY:
case wasm::WASM_EXTERNAL_TABLE:
break;
default: default:
// TODO(sbc): Handle other kinds of exports
return make_error<GenericBinaryError>( return make_error<GenericBinaryError>(
"Unexpected export kind", object_error::parse_failed); "Unexpected export kind", object_error::parse_failed);
} }
@ -638,10 +653,14 @@ basic_symbol_iterator WasmObjectFile::symbol_end() const {
return BasicSymbolRef(Ref, this); return BasicSymbolRef(Ref, this);
} }
const WasmSymbol &WasmObjectFile::getWasmSymbol(DataRefImpl Symb) const { const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
return Symbols[Symb.d.a]; return Symbols[Symb.d.a];
} }
const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
return getWasmSymbol(Symb.getRawDataRefImpl());
}
Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
const WasmSymbol &Sym = getWasmSymbol(Symb); const WasmSymbol &Sym = getWasmSymbol(Symb);
return Sym.Name; return Sym.Name;

View File

@ -265,8 +265,12 @@ void MappingTraits<WasmYAML::Import>::mapping(IO &IO,
if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) { if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
IO.mapRequired("SigIndex", Import.SigIndex); IO.mapRequired("SigIndex", Import.SigIndex);
} else if (Import.Kind == wasm::WASM_EXTERNAL_GLOBAL) { } else if (Import.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
IO.mapRequired("GlobalType", Import.GlobalType); IO.mapRequired("GlobalType", Import.Global.Type);
IO.mapRequired("GlobalMutable", Import.GlobalMutable); IO.mapRequired("GlobalMutable", Import.Global.Mutable);
} else if (Import.Kind == wasm::WASM_EXTERNAL_TABLE) {
IO.mapRequired("Table", Import.Table);
} else if (Import.Kind == wasm::WASM_EXTERNAL_MEMORY ) {
IO.mapRequired("Memory", Import.Memory);
} else { } else {
llvm_unreachable("unhandled import type"); llvm_unreachable("unhandled import type");
} }

View File

@ -5,12 +5,18 @@ FileHeader:
Sections: Sections:
- Type: EXPORT - Type: EXPORT
Exports: Exports:
- Name: foo - Name: function_export
Kind: FUNCTION
Index: 0
- Name: bar
Kind: FUNCTION Kind: FUNCTION
Index: 1 Index: 1
- Name: global_export
Kind: GLOBAL
Index: 1
- Name: memory_export
Kind: MEMORY
Index: 0
- Name: table_export
Kind: TABLE
Index: 0
... ...
# CHECK: --- !WASM # CHECK: --- !WASM
# CHECK: FileHeader: # CHECK: FileHeader:
@ -18,10 +24,16 @@ Sections:
# CHECK: Sections: # CHECK: Sections:
# CHECK: - Type: EXPORT # CHECK: - Type: EXPORT
# CHECK: Exports: # CHECK: Exports:
# CHECK: - Name: foo # CHECK: - Name: function_export
# CHECK: Kind: FUNCTION
# CHECK: Index: 0
# CHECK: - Name: bar
# CHECK: Kind: FUNCTION # CHECK: Kind: FUNCTION
# CHECK: Index: 1 # CHECK: Index: 1
# CHECK: - Name: global_export
# CHECK: Kind: GLOBAL
# CHECK: Index: 1
# CHECK: - Name: memory_export
# CHECK: Kind: MEMORY
# CHECK: Index: 0
# CHECK: - Name: table_export
# CHECK: Kind: TABLE
# CHECK: Index: 0
# CHECK: ... # CHECK: ...

View File

@ -9,19 +9,32 @@ Sections:
ParamTypes: ParamTypes:
- I32 - I32
- Type: IMPORT - Type: IMPORT
Imports: Imports:
- Module: foo - Module: foo
Field: bar Field: imported_function
Kind: FUNCTION Kind: FUNCTION
SigIndex: 0 SigIndex: 0
- Module: fiz - Module: fiz
Field: baz Field: imported_global
Kind: GLOBAL Kind: GLOBAL
GlobalType: I32 GlobalType: I32
GlobalMutable: false GlobalMutable: false
- Type: FUNCTION - Module: foo
FunctionTypes: Field: imported_memory
- 0 Kind: MEMORY
Memory:
Flags: 0x00000001
Initial: 0x00000010
Maximum: 0x00000011
- Module: foo
Field: imported_table
Kind: TABLE
Table:
ElemType: ANYFUNC
Limits:
Flags: 0x00000001
Initial: 0x00000020
Maximum: 0x00000022
... ...
# CHECK: --- !WASM # CHECK: --- !WASM
# CHECK: FileHeader: # CHECK: FileHeader:
@ -30,12 +43,28 @@ Sections:
# CHECK: - Type: IMPORT # CHECK: - Type: IMPORT
# CHECK: Imports: # CHECK: Imports:
# CHECK: - Module: foo # CHECK: - Module: foo
# CHECK: Field: bar # CHECK: Field: imported_function
# CHECK: Kind: FUNCTION # CHECK: Kind: FUNCTION
# CHECK: SigIndex: 0 # CHECK: SigIndex: 0
# CHECK: - Module: fiz # CHECK: - Module: fiz
# CHECK: Field: baz # CHECK: Field: imported_global
# CHECK: Kind: GLOBAL # CHECK: Kind: GLOBAL
# CHECK: GlobalType: I32 # CHECK: GlobalType: I32
# CHECK: GlobalMutable: false # CHECK: GlobalMutable: false
# CHECK: - Module: foo
# CHECK: Field: imported_memory
# CHECK: Kind: MEMORY
# CHECK: Memory:
# CHECK: Flags: 0x00000001
# CHECK: Initial: 0x00000010
# CHECK: Maximum: 0x00000011
# CHECK: - Module: foo
# CHECK: Field: imported_table
# CHECK: Kind: TABLE
# CHECK: Table:
# CHECK: ElemType: ANYFUNC
# CHECK: Limits:
# CHECK: Flags: 0x00000001
# CHECK: Initial: 0x00000020
# CHECK: Maximum: 0x00000022
# CHECK: ... # CHECK: ...

View File

@ -25,6 +25,23 @@ public:
ErrorOr<WasmYAML::Object *> dump(); ErrorOr<WasmYAML::Object *> dump();
}; };
WasmYAML::Table make_table(const wasm::WasmTable &Table) {
WasmYAML::Table T;
T.ElemType = Table.ElemType;
T.TableLimits.Flags = Table.Limits.Flags;
T.TableLimits.Initial = Table.Limits.Initial;
T.TableLimits.Maximum = Table.Limits.Maximum;
return T;
}
WasmYAML::Limits make_limits(const wasm::WasmLimits &Limits) {
WasmYAML::Limits L;
L.Flags = Limits.Flags;
L.Initial = Limits.Initial;
L.Maximum = Limits.Maximum;
return L;
}
ErrorOr<WasmYAML::Object *> WasmDumper::dump() { ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
auto Y = make_unique<WasmYAML::Object>(); auto Y = make_unique<WasmYAML::Object>();
@ -82,17 +99,26 @@ ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
case wasm::WASM_SEC_IMPORT: { case wasm::WASM_SEC_IMPORT: {
auto ImportSec = make_unique<WasmYAML::ImportSection>(); auto ImportSec = make_unique<WasmYAML::ImportSection>();
for (auto &Import : Obj.imports()) { for (auto &Import : Obj.imports()) {
WasmYAML::Import Ex; WasmYAML::Import Im;
Ex.Module = Import.Module; Im.Module = Import.Module;
Ex.Field = Import.Field; Im.Field = Import.Field;
Ex.Kind = Import.Kind; Im.Kind = Import.Kind;
if (Ex.Kind == wasm::WASM_EXTERNAL_FUNCTION) { switch (Im.Kind) {
Ex.SigIndex = Import.SigIndex; case wasm::WASM_EXTERNAL_FUNCTION:
} else if (Ex.Kind == wasm::WASM_EXTERNAL_GLOBAL) { Im.SigIndex = Import.SigIndex;
Ex.GlobalType = Import.GlobalType; break;
Ex.GlobalMutable = Import.GlobalMutable; case wasm::WASM_EXTERNAL_GLOBAL:
Im.Global.Type = Import.Global.Type;
Im.Global.Mutable = Import.Global.Mutable;
break;
case wasm::WASM_EXTERNAL_TABLE:
Im.Table = make_table(Import.Table);
break;
case wasm::WASM_EXTERNAL_MEMORY:
Im.Memory = make_limits(Import.Memory);
break;
} }
ImportSec->Imports.push_back(Ex); ImportSec->Imports.push_back(Im);
} }
S = std::move(ImportSec); S = std::move(ImportSec);
break; break;
@ -107,25 +133,16 @@ ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
} }
case wasm::WASM_SEC_TABLE: { case wasm::WASM_SEC_TABLE: {
auto TableSec = make_unique<WasmYAML::TableSection>(); auto TableSec = make_unique<WasmYAML::TableSection>();
for (auto &Table : Obj.tables()) { for (const wasm::WasmTable &Table : Obj.tables()) {
WasmYAML::Table T; TableSec->Tables.push_back(make_table(Table));
T.ElemType = Table.ElemType;
T.TableLimits.Flags = Table.Limits.Flags;
T.TableLimits.Initial = Table.Limits.Initial;
T.TableLimits.Maximum = Table.Limits.Maximum;
TableSec->Tables.push_back(T);
} }
S = std::move(TableSec); S = std::move(TableSec);
break; break;
} }
case wasm::WASM_SEC_MEMORY: { case wasm::WASM_SEC_MEMORY: {
auto MemorySec = make_unique<WasmYAML::MemorySection>(); auto MemorySec = make_unique<WasmYAML::MemorySection>();
for (auto &Memory : Obj.memories()) { for (const wasm::WasmLimits &Memory : Obj.memories()) {
WasmYAML::Limits L; MemorySec->Memories.push_back(make_limits(Memory));
L.Flags = Memory.Flags;
L.Initial = Memory.Initial;
L.Maximum = Memory.Maximum;
MemorySec->Memories.push_back(L);
} }
S = std::move(MemorySec); S = std::move(MemorySec);
break; break;

View File

@ -169,8 +169,15 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
encodeULEB128(Import.SigIndex, OS); encodeULEB128(Import.SigIndex, OS);
break; break;
case wasm::WASM_EXTERNAL_GLOBAL: case wasm::WASM_EXTERNAL_GLOBAL:
encodeSLEB128(Import.GlobalType, OS); encodeSLEB128(Import.Global.Type, OS);
writeUint8(OS, Import.GlobalMutable); writeUint8(OS, Import.Global.Mutable);
break;
case wasm::WASM_EXTERNAL_MEMORY:
writeLimits(Import.Memory, OS);
break;
case wasm::WASM_EXTERNAL_TABLE:
encodeSLEB128(Import.Table.ElemType, OS);
writeLimits(Import.Table.TableLimits, OS);
break; break;
default: default:
errs() << "Unknown import type: " << Import.Kind; errs() << "Unknown import type: " << Import.Kind;