mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-30 23:21:04 +00:00
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313795 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
686e2d6ca3
commit
81e3824428
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -9,6 +9,14 @@ target triple = "wasm32-unknown-unknown-wasm"
|
||||
|
||||
@gBd = hidden global [2 x %struct.bd] [%struct.bd { i8 1 }, %struct.bd { i8 2 }], align 1
|
||||
|
||||
; CHECK: - Type: DATA
|
||||
; CHECK: Content: '0102'
|
||||
; CHECK: DataSize: 2
|
||||
; CHECK: - Type: DATA
|
||||
; CHECK: Content: '0102'
|
||||
|
||||
; 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: ...
|
||||
|
20
test/MC/WebAssembly/bss.ll
Normal file
20
test/MC/WebAssembly/bss.ll
Normal 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: ...
|
@ -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: ...
|
||||
|
@ -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: ...
|
||||
|
@ -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: ...
|
||||
|
@ -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)
|
||||
|
@ -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()) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user