diff --git a/lld/test/wasm/data-segment-merging.ll b/lld/test/wasm/data-segment-merging.ll --- a/lld/test/wasm/data-segment-merging.ll +++ b/lld/test/wasm/data-segment-merging.ll @@ -12,6 +12,8 @@ ; RUN: wasm-ld -no-gc-sections --no-entry -o %t.merged.wasm %t.data-segment-merging.o ; RUN: obj2yaml %t.merged.wasm | FileCheck %s --check-prefix=MERGE + +; MERGE-NOT: DATACOUNT ; MERGE: - Type: DATA ; MERGE: Segments: ; MERGE: Content: 68656C6C6F00676F6F6462796500776861746576657200002A000000 @@ -20,6 +22,8 @@ ; RUN: wasm-ld -no-gc-sections --no-entry --no-merge-data-segments -o %t.separate.wasm %t.data-segment-merging.o ; RUN: obj2yaml %t.separate.wasm | FileCheck %s --check-prefix=SEPARATE + +; SEPARATE-NOT: DATACOUNT ; SEPARATE: - Type: DATA ; SEPARATE: Segments: ; SEPARATE: Content: 68656C6C6F00 @@ -29,3 +33,15 @@ ; SEPARATE: Content: 636F6E7374616E7400 ; SEPARATE: Content: 2B ; SEPARATE-NOT: Content: + +; RUN: llc -filetype=obj %s -mattr=+bulk-memory -o %t.data-segment-merging.bulk-memory.o +; RUN: wasm-ld -no-gc-sections --no-entry -o %t.merged.bulk-memory.wasm %t.data-segment-merging.bulk-memory.o +; RUN: obj2yaml %t.merged.bulk-memory.wasm | FileCheck %s --check-prefix=BULK-MEMORY + +; BULK-MEMORY: - Type: DATACOUNT +; BULK-MEMORY: Count: 2 +; BULK-MEMORY: - Type: DATA +; BULK-MEMORY: Segments: +; BULK-MEMORY: Content: 68656C6C6F00676F6F6462796500776861746576657200002A000000 +; BULK-MEMORY: Content: 636F6E7374616E74000000002B +; BULK-MEMORY-NOT: Content: diff --git a/lld/wasm/OutputSections.h b/lld/wasm/OutputSections.h --- a/lld/wasm/OutputSections.h +++ b/lld/wasm/OutputSections.h @@ -82,6 +82,16 @@ llvm::raw_string_ostream BodyOutputStream; }; +class DataCountSection : public OutputSection { +public: + explicit DataCountSection(size_t Count); + size_t getSize() const override { return Header.size() + Contents.size(); } + void writeTo(uint8_t *Buf) override; + +protected: + std::string Contents; +}; + class CodeSection : public OutputSection { public: explicit CodeSection(ArrayRef Functions); diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp --- a/lld/wasm/OutputSections.cpp +++ b/lld/wasm/OutputSections.cpp @@ -51,6 +51,8 @@ return "CODE"; case WASM_SEC_DATA: return "DATA"; + case WASM_SEC_DATACOUNT: + return "DATACOUNT"; default: fatal("invalid section type"); } @@ -77,6 +79,29 @@ " total=" + Twine(getSize())); } +DataCountSection::DataCountSection(size_t Count) + : OutputSection(WASM_SEC_DATACOUNT) { + raw_string_ostream OS(Contents); + writeUleb128(OS, Count, "segment count"); + OS.flush(); + createHeader(Contents.size()); +} + +void DataCountSection::writeTo(uint8_t *Buf) { + log("writing " + toString(*this)); + log(" size=" + Twine(getSize())); + log(" headersize=" + Twine(Header.size())); + log(" contentsize=" + Twine(Contents.size())); + Buf += Offset; + + // Write section Header + memcpy(Buf, Header.data(), Header.size()); + Buf += Header.size(); + + // Write data count section contents + memcpy(Buf, Contents.data(), Contents.size()); +} + CodeSection::CodeSection(ArrayRef Functions) : OutputSection(WASM_SEC_CODE), Functions(Functions) { assert(Functions.size() > 0); diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -93,6 +93,7 @@ void createImportSection(); void createMemorySection(); void createElemSection(); + void createDataCountSection(); void createCodeSection(); void createDataSection(); void createCustomSections(); @@ -414,6 +415,15 @@ } } +void Writer::createDataCountSection() { + if (!Segments.size() || !TargetFeatures.count("bulk-memory")) + return; + log("createDataCountSection"); + + auto Section = make(Segments.size()); + OutputSections.push_back(Section); +} + void Writer::createCodeSection() { if (InputFunctions.empty()) return; @@ -865,6 +875,7 @@ createEventSection(); createExportSection(); createElemSection(); + createDataCountSection(); createCodeSection(); createDataSection(); createCustomSections();