[WebAssembly] Expose the offset of each data segment

Summary:
This allows tools like lld that process relocations
to apply data relocation correctly. This information
is required because relocation are stored as section
offset.

Subscribers: jfb, dschuff, jgravelle-google, aheejin

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

llvm-svn: 307741
diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h
index 4cb373a..23e30b7 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -94,7 +94,7 @@
 };
 
 struct WasmDataSegment {
-  uint32_t Index;
+  uint32_t MemoryIndex;
   WasmInitExpr Offset;
   ArrayRef<uint8_t> Content;
 };
diff --git a/llvm/include/llvm/Object/Wasm.h b/llvm/include/llvm/Object/Wasm.h
index f1c140c..07ee4a4 100644
--- a/llvm/include/llvm/Object/Wasm.h
+++ b/llvm/include/llvm/Object/Wasm.h
@@ -69,8 +69,7 @@
 #endif
 };
 
-class WasmSection {
-public:
+struct WasmSection {
   WasmSection() = default;
 
   uint32_t Type = 0; // Section type (See below)
@@ -80,6 +79,11 @@
   std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
 };
 
+struct WasmSegment {
+  uint32_t SectionOffset;
+  wasm::WasmDataSegment Data;
+};
+
 class WasmObjectFile : public ObjectFile {
 
 public:
@@ -110,7 +114,7 @@
     return ElemSegments;
   }
 
-  const std::vector<wasm::WasmDataSegment>& dataSegments() const {
+  const std::vector<WasmSegment>& dataSegments() const {
     return DataSegments;
   }
 
@@ -210,7 +214,7 @@
   std::vector<wasm::WasmImport> Imports;
   std::vector<wasm::WasmExport> Exports;
   std::vector<wasm::WasmElemSegment> ElemSegments;
-  std::vector<wasm::WasmDataSegment> DataSegments;
+  std::vector<WasmSegment> DataSegments;
   std::vector<wasm::WasmFunction> Functions;
   std::vector<WasmSymbol> Symbols;
   ArrayRef<uint8_t> CodeSection;
diff --git a/llvm/include/llvm/ObjectYAML/WasmYAML.h b/llvm/include/llvm/ObjectYAML/WasmYAML.h
index 6bf08d3..709ad8e 100644
--- a/llvm/include/llvm/ObjectYAML/WasmYAML.h
+++ b/llvm/include/llvm/ObjectYAML/WasmYAML.h
@@ -98,7 +98,8 @@
 };
 
 struct DataSegment {
-  uint32_t Index;
+  uint32_t MemoryIndex;
+  uint32_t SectionOffset;
   wasm::WasmInitExpr Offset;
   yaml::BinaryRef Content;
 };
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index 3c675aa..7f80bf0 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -675,15 +675,17 @@
 }
 
 Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) {
+  const uint8_t *Start = Ptr;
   uint32_t Count = readVaruint32(Ptr);
   DataSegments.reserve(Count);
   while (Count--) {
-    wasm::WasmDataSegment Segment;
-    Segment.Index = readVaruint32(Ptr);
-    if (Error Err = readInitExpr(Segment.Offset, Ptr))
+    WasmSegment Segment;
+    Segment.Data.MemoryIndex = readVaruint32(Ptr);
+    if (Error Err = readInitExpr(Segment.Data.Offset, Ptr))
       return Err;
     uint32_t Size = readVaruint32(Ptr);
-    Segment.Content = ArrayRef<uint8_t>(Ptr, Size);
+    Segment.Data.Content = ArrayRef<uint8_t>(Ptr, Size);
+    Segment.SectionOffset = Ptr - Start;
     Ptr += Size;
     DataSegments.push_back(Segment);
   }
diff --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp
index 2040efd..6a68cd2 100644
--- a/llvm/lib/ObjectYAML/WasmYAML.cpp
+++ b/llvm/lib/ObjectYAML/WasmYAML.cpp
@@ -345,7 +345,8 @@
 
 void MappingTraits<WasmYAML::DataSegment>::mapping(
     IO &IO, WasmYAML::DataSegment &Segment) {
-  IO.mapRequired("Index", Segment.Index);
+  IO.mapOptional("SectionOffset", Segment.SectionOffset);
+  IO.mapRequired("MemoryIndex", Segment.MemoryIndex);
   IO.mapRequired("Offset", Segment.Offset);
   IO.mapRequired("Content", Segment.Content);
 }
diff --git a/llvm/test/MC/WebAssembly/external-data.ll b/llvm/test/MC/WebAssembly/external-data.ll
index 6914736..b8c9745 100644
--- a/llvm/test/MC/WebAssembly/external-data.ll
+++ b/llvm/test/MC/WebAssembly/external-data.ll
@@ -13,7 +13,8 @@
 ; CHECK:         Index:           0
 ; CHECK:         Offset:          0x0000000E
 ; CHECK:     Segments:
-; CHECK:       - Index:           0
+; CHECK:       - SectionOffset:   6
+; CHECK:         MemoryIndex:     0
 ; CHECK:         Offset:
 ; CHECK:           Opcode:          I32_CONST
 ; CHECK:           Value:           0
diff --git a/llvm/test/MC/WebAssembly/unnamed-data.ll b/llvm/test/MC/WebAssembly/unnamed-data.ll
index fd98508..fa0ff96 100644
--- a/llvm/test/MC/WebAssembly/unnamed-data.ll
+++ b/llvm/test/MC/WebAssembly/unnamed-data.ll
@@ -46,7 +46,8 @@
 ; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:         Offset:          0x0000001E
 ; CHECK-NEXT:     Segments:        
-; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:       - SectionOffset:   6
+; CHECK-NEXT:         MemoryIndex:     0
 ; CHECK-NEXT:         Offset:          
 ; CHECK-NEXT:           Opcode:          I32_CONST
 ; CHECK-NEXT:           Value:           0
diff --git a/llvm/test/ObjectYAML/wasm/data_section.yaml b/llvm/test/ObjectYAML/wasm/data_section.yaml
index b8c65ab..521aa54 100644
--- a/llvm/test/ObjectYAML/wasm/data_section.yaml
+++ b/llvm/test/ObjectYAML/wasm/data_section.yaml
@@ -8,7 +8,7 @@
       - Initial:         0x00000003
   - Type:            DATA
     Segments:
-      - Index:           0
+      - MemoryIndex:      0
         Offset:
           Opcode:          I32_CONST
           Value:           4
@@ -38,7 +38,8 @@
 # CHECK-NEXT:        Offset:          0x00000006
 # CHECK-NEXT:        Addend:          -6
 # CHECK-NEXT:     Segments:
-# CHECK-NEXT:       - Index:           0
+# CHECK-NEXT:       - SectionOffset:   6
+# CHECK-NEXT:         MemoryIndex:     0
 # CHECK-NEXT:         Offset:
 # CHECK-NEXT:           Opcode:          I32_CONST
 # CHECK-NEXT:           Value:           4
diff --git a/llvm/tools/obj2yaml/wasm2yaml.cpp b/llvm/tools/obj2yaml/wasm2yaml.cpp
index 1df6afc..a1da4b6 100644
--- a/llvm/tools/obj2yaml/wasm2yaml.cpp
+++ b/llvm/tools/obj2yaml/wasm2yaml.cpp
@@ -236,9 +236,10 @@
       auto DataSec = make_unique<WasmYAML::DataSection>();
       for (auto &Segment : Obj.dataSegments()) {
         WasmYAML::DataSegment Seg;
-        Seg.Index = Segment.Index;
-        Seg.Offset = Segment.Offset;
-        Seg.Content = yaml::BinaryRef(Segment.Content);
+        Seg.SectionOffset = Segment.SectionOffset;
+        Seg.MemoryIndex = Segment.Data.MemoryIndex;
+        Seg.Offset = Segment.Data.Offset;
+        Seg.Content = yaml::BinaryRef(Segment.Data.Content);
         DataSec->Segments.push_back(Seg);
       }
       S = std::move(DataSec);
diff --git a/llvm/tools/yaml2obj/yaml2wasm.cpp b/llvm/tools/yaml2obj/yaml2wasm.cpp
index 110700d..059ec5f 100644
--- a/llvm/tools/yaml2obj/yaml2wasm.cpp
+++ b/llvm/tools/yaml2obj/yaml2wasm.cpp
@@ -338,7 +338,7 @@
                                     WasmYAML::DataSection &Section) {
   encodeULEB128(Section.Segments.size(), OS);
   for (auto &Segment : Section.Segments) {
-    encodeULEB128(Segment.Index, OS);
+    encodeULEB128(Segment.MemoryIndex, OS);
     writeInitExpr(Segment.Offset, OS);
     encodeULEB128(Segment.Content.binary_size(), OS);
     Segment.Content.writeAsBinary(OS);