Reland "[WebAssembly] Add support for naming wasm data segments"

Add adds support for naming data segments.  This is useful
useful linkers so that they can merge similar sections.

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

llvm-svn: 313795
This commit is contained in:
Sam Clegg 2017-09-20 19:03:35 +00:00
parent 01a409520b
commit d95ed959d8
14 changed files with 130 additions and 9 deletions

View File

@ -97,6 +97,7 @@ struct WasmDataSegment {
uint32_t MemoryIndex;
WasmInitExpr Offset;
ArrayRef<uint8_t> Content;
StringRef Name;
};
struct WasmElemSegment {
@ -184,6 +185,7 @@ enum : unsigned {
WASM_SYMBOL_INFO = 0x2,
WASM_DATA_SIZE = 0x3,
WASM_DATA_ALIGNMENT = 0x4,
WASM_SEGMENT_NAMES = 0x5,
};
enum : unsigned {

View File

@ -160,9 +160,10 @@ struct LinkingSection : CustomSection {
return C && C->Name == "linking";
}
std::vector<SymbolInfo> SymbolInfos;
uint32_t DataSize;
uint32_t DataAlignment;
std::vector<SymbolInfo> SymbolInfos;
std::vector<NameEntry> SegmentNames;
};
struct TypeSection : Section {

View File

@ -102,6 +102,7 @@ struct WasmFunctionTypeDenseMapInfo {
// wasm data segment.
struct WasmDataSegment {
MCSectionWasm *Section;
StringRef Name;
uint32_t Offset;
SmallVector<char, 4> Data;
};
@ -279,7 +280,8 @@ private:
uint32_t NumFuncImports);
void writeCodeRelocSection();
void writeDataRelocSection();
void writeLinkingMetaDataSection(uint32_t DataSize, uint32_t DataAlignment,
void writeLinkingMetaDataSection(ArrayRef<WasmDataSegment> Segments,
uint32_t DataSize, uint32_t DataAlignment,
ArrayRef<StringRef> WeakSymbols,
bool HasStackPointer,
uint32_t StackPointerGlobal);
@ -911,7 +913,8 @@ void WasmObjectWriter::writeDataRelocSection() {
}
void WasmObjectWriter::writeLinkingMetaDataSection(
uint32_t DataSize, uint32_t DataAlignment, ArrayRef<StringRef> WeakSymbols,
ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
uint32_t DataAlignment, ArrayRef<StringRef> WeakSymbols,
bool HasStackPointer, uint32_t StackPointerGlobal) {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
@ -943,6 +946,14 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
endSection(SubSection);
}
if (Segments.size()) {
startSection(SubSection, wasm::WASM_SEGMENT_NAMES);
encodeULEB128(Segments.size(), getStream());
for (const WasmDataSegment &Segment : Segments)
writeString(Segment.Name);
endSection(SubSection);
}
endSection(Section);
}
@ -1129,6 +1140,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
DataSize = alignTo(DataSize, Section.getAlignment());
DataSegments.emplace_back();
WasmDataSegment &Segment = DataSegments.back();
Segment.Name = Section.getSectionName();
Segment.Offset = DataSize;
Segment.Section = &Section;
addData(Segment.Data, Section, DataAlignment);
@ -1288,7 +1300,8 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
writeNameSection(Functions, Imports, NumFuncImports);
writeCodeRelocSection();
writeDataRelocSection();
writeLinkingMetaDataSection(DataSize, DataAlignment, WeakSymbols, HasStackPointer, StackPointerGlobal);
writeLinkingMetaDataSection(DataSegments, DataSize, DataAlignment,
WeakSymbols, HasStackPointer, StackPointerGlobal);
// TODO: Translate the .comment section to the output.
// TODO: Translate debug sections to the output.

View File

@ -396,6 +396,15 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
case wasm::WASM_DATA_ALIGNMENT:
LinkingData.DataAlignment = readVaruint32(Ptr);
break;
case wasm::WASM_SEGMENT_NAMES: {
uint32_t Count = readVaruint32(Ptr);
if (Count > DataSegments.size())
return make_error<GenericBinaryError>("Too many segment names",
object_error::parse_failed);
for (uint32_t i = 0; i < Count; i++)
DataSegments[i].Data.Name = readString(Ptr);
break;
}
case wasm::WASM_STACK_POINTER:
default:
Ptr += Size;

View File

@ -60,6 +60,7 @@ static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
IO.mapRequired("DataSize", Section.DataSize);
IO.mapRequired("DataAlignment", Section.DataAlignment);
IO.mapOptional("SymbolInfo", Section.SymbolInfos);
IO.mapOptional("SegmentNames", Section.SegmentNames);
}
static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {

View File

@ -11,4 +11,12 @@ target triple = "wasm32-unknown-unknown-wasm"
; CHECK: - Type: DATA
; CHECK: Content: '0102'
; CHECK: DataSize: 2
; CHECK: - Type: CUSTOM
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 2
; CHECK-NEXT: DataAlignment: 1
; CHECK-NEXT: SegmentNames:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: .data
; CHECK-NEXT: ...

View File

@ -0,0 +1,20 @@
; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj %s -o - | obj2yaml | FileCheck %s
@g0 = global i8* null, align 4
; CHECK: - Type: DATA
; CHECK-NEXT: Segments:
; CHECK-NEXT: - SectionOffset: 6
; CHECK-NEXT: MemoryIndex: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 0
; CHECK-NEXT: Content: '00000000'
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 4
; CHECK-NEXT: DataAlignment: 4
; CHECK-NEXT: SegmentNames:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: .bss.g0
; CHECK-NEXT: ...

View File

@ -63,3 +63,16 @@
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 24
; CHECK-NEXT: Content: '08000000'
; CHECK: - Type: CUSTOM
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 28
; CHECK-NEXT: DataAlignment: 8
; CHECK-NEXT: SegmentNames:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: .data.global0
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Name: .sec1
; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Name: .sec2
; CHECK-NEXT: ...

View File

@ -74,4 +74,13 @@
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 28
; CHECK-NEXT: DataAlignment: 8
; CHECK-NEXT: SegmentNames:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: .rodata..L.str1
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Name: .rodata..L.str2
; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Name: .data.a
; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Name: .data.b
; CHECK-NEXT: ...

View File

@ -101,4 +101,9 @@ entry:
; CHECK-NEXT: Flags: 1
; CHECK-NEXT: - Name: bar_alias
; CHECK-NEXT: Flags: 1
; CHECK-NEXT: SegmentNames:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: .data.bar
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Name: .data.bar_alias_address
; CHECK-NEXT: ...

View File

@ -543,6 +543,12 @@ WASM-NEXT: Section {
WASM-NEXT: Type: DATA (0xB)
WASM-NEXT: Size: 19
WASM-NEXT: Offset: 154
WASM-NEXT: Segments [
WASM-NEXT: Segment {
WASM-NEXT: Size: 13
WASM-NEXT: Offset: 0
WASM-NEXT: }
WASM-NEXT: ]
WASM-NEXT: }
WASM-NEXT: Section {
WASM-NEXT: Type: CUSTOM (0x0)

View File

@ -148,7 +148,7 @@ void WasmDumper::printSections() {
const WasmSection &WasmSec = Obj->getWasmSection(Section);
DictScope SectionD(W, "Section");
W.printEnum("Type", WasmSec.Type, makeArrayRef(WasmSectionTypes));
W.printNumber("Size", (uint64_t)WasmSec.Content.size());
W.printNumber("Size", static_cast<uint64_t>(WasmSec.Content.size()));
W.printNumber("Offset", WasmSec.Offset);
switch (WasmSec.Type) {
case wasm::WASM_SEC_CUSTOM:
@ -160,6 +160,19 @@ void WasmDumper::printSections() {
W.printNumber("DataAlignment", LinkingData.DataAlignment);
}
break;
case wasm::WASM_SEC_DATA: {
ListScope Group(W, "Segments");
for (const WasmSegment &Segment : Obj->dataSegments()) {
const wasm::WasmDataSegment& Seg = Segment.Data;
DictScope Group(W, "Segment");
if (!Seg.Name.empty())
W.printString("Name", Seg.Name);
W.printNumber("Size", static_cast<uint64_t>(Seg.Content.size()));
if (Seg.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST)
W.printNumber("Offset", Seg.Offset.Value.Int32);
}
break;
}
case wasm::WASM_SEC_MEMORY:
ListScope Group(W, "Memories");
for (const wasm::WasmLimits &Memory : Obj->memories()) {

View File

@ -70,6 +70,16 @@ std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const Was
CustomSec = std::move(NameSec);
} else if (WasmSec.Name == "linking") {
std::unique_ptr<WasmYAML::LinkingSection> LinkingSec = make_unique<WasmYAML::LinkingSection>();
size_t Index = 0;
for (const object::WasmSegment &Segment : Obj.dataSegments()) {
if (!Segment.Data.Name.empty()) {
WasmYAML::NameEntry NameEntry;
NameEntry.Name = Segment.Data.Name;
NameEntry.Index = Index;
LinkingSec->SegmentNames.push_back(NameEntry);
}
Index++;
}
for (const object::SymbolRef& Sym: Obj.symbols()) {
const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym);
if (Symbol.Flags != 0) {
@ -234,7 +244,7 @@ ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
}
case wasm::WASM_SEC_DATA: {
auto DataSec = make_unique<WasmYAML::DataSection>();
for (auto &Segment : Obj.dataSegments()) {
for (const object::WasmSegment &Segment : Obj.dataSegments()) {
WasmYAML::DataSegment Seg;
Seg.SectionOffset = Segment.SectionOffset;
Seg.MemoryIndex = Segment.Data.MemoryIndex;

View File

@ -157,6 +157,17 @@ int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &S
SubSection.Done();
}
// SEGMENT_NAMES subsection
if (Section.SegmentNames.size()) {
encodeULEB128(wasm::WASM_SEGMENT_NAMES, OS);
encodeULEB128(Section.SegmentNames.size(), SubSection.GetStream());
for (const WasmYAML::NameEntry &NameEntry : Section.SegmentNames) {
encodeULEB128(NameEntry.Index, SubSection.GetStream());
writeStringRef(NameEntry.Name, SubSection.GetStream());
}
SubSection.Done();
}
return 0;
}